From 8ee0cd905c894d8294ada94bf0adeacd1ea55b84 Mon Sep 17 00:00:00 2001 From: Leopold Palomo-Avellaneda Date: Mon, 6 Oct 2014 09:24:27 +0200 Subject: [PATCH] Imported Upstream version 1.7.2 --- .travis.sh | 135 + .travis.yml | 42 +- CHANGES.md | 279 + CMakeLists.txt | 267 +- CONTRIBUTING.md | 147 + PCLConfig.cmake.in | 96 +- apps/CMakeLists.txt | 170 +- apps/cloud_composer/CMakeLists.txt | 135 +- apps/cloud_composer/ComposerTool.cmake | 4 + .../pcl/apps/cloud_composer/cloud_view.h | 1 + .../pcl/apps/cloud_composer/project_model.h | 2 +- apps/cloud_composer/src/cloud_view.cpp | 9 +- apps/cloud_composer/src/commands.cpp | 6 +- apps/cloud_composer/src/item_inspector.cpp | 2 +- .../src/items/cloud_composer_item.cpp | 4 +- apps/cloud_composer/src/merge_selection.cpp | 21 +- .../rectangular_frustum_selector.cpp | 15 +- apps/cloud_composer/src/project_model.cpp | 6 +- apps/cloud_composer/src/properties_model.cpp | 5 +- apps/cloud_composer/src/toolbox_model.cpp | 6 +- apps/cloud_composer/tools/sanitize_cloud.cpp | 5 +- .../tools/voxel_grid_downsample.cpp | 2 +- apps/in_hand_scanner/CMakeLists.txt | 153 +- apps/in_hand_scanner/src/opengl_viewer.cpp | 11 +- .../apps/impl/dominant_plane_segmentation.hpp | 20 +- apps/modeler/CMakeLists.txt | 103 +- apps/modeler/src/icp_registration_worker.cpp | 2 +- apps/modeler/src/normals_actor_item.cpp | 6 +- apps/modeler/src/points_actor_item.cpp | 7 +- apps/modeler/src/surface_actor_item.cpp | 7 +- apps/optronic_viewer/CMakeLists.txt | 98 +- apps/point_cloud_editor/CMakeLists.txt | 166 +- .../pcl/apps/point_cloud_editor/cutCommand.h | 14 +- .../apps/point_cloud_editor/deleteCommand.h | 14 +- .../apps/point_cloud_editor/pasteCommand.h | 12 +- .../point_cloud_editor/transformCommand.h | 16 +- .../src/cloudEditorWidget.cpp | 10 +- .../src/statisticsDialog.cpp | 2 +- apps/src/convolve.cpp | 21 +- apps/src/grabcut_2d.cpp | 565 + apps/src/ni_linemod.cpp | 4 +- apps/src/ni_trajkovic.cpp | 249 + apps/src/openni_klt.cpp | 408 + ...nni_organized_multi_plane_segmentation.cpp | 6 +- ...pcd_organized_multi_plane_segmentation.cpp | 2 +- apps/src/pcd_select_object_plane.cpp | 16 +- apps/src/render_views_tesselated_sphere.cpp | 5 +- cmake/Modules/FindEigen.cmake | 20 +- cmake/Modules/FindFZAPI.cmake | 7 - cmake/Modules/FindGLEW.cmake | 8 +- cmake/Modules/FindGtest.cmake | 40 + cmake/Modules/FindMPI.cmake | 617 - cmake/Modules/FindOpenNI.cmake | 23 +- cmake/Modules/FindOpenNI2.cmake | 80 + cmake/Modules/FindPXCAPI.cmake | 37 +- cmake/Modules/FindPcap.cmake | 11 +- cmake/Modules/FindQVTK.cmake | 37 +- cmake/Modules/FindQhull.cmake | 8 +- cmake/pcl_find_boost.cmake | 31 +- cmake/pcl_find_gl.cmake | 20 + cmake/pcl_options.cmake | 14 + cmake/pcl_pclconfig.cmake | 24 +- cmake/pcl_targets.cmake | 180 +- cmake/pcl_utils.cmake | 22 +- cmake/uninstall_target.cmake.in | 32 +- common/CMakeLists.txt | 42 +- common/include/pcl/PCLHeader.h | 7 +- common/include/pcl/common/centroid.h | 182 + common/include/pcl/common/copy_point.h | 62 + common/include/pcl/common/eigen.h | 888 +- .../include/pcl/common/impl/accumulators.hpp | 296 + common/include/pcl/common/impl/centroid.hpp | 53 +- common/include/pcl/common/impl/copy_point.hpp | 145 + common/include/pcl/common/impl/eigen.hpp | 748 +- .../include/pcl/common/impl/intersections.hpp | 172 + common/include/pcl/common/impl/io.hpp | 453 +- common/include/pcl/common/impl/pca.hpp | 6 +- common/include/pcl/common/intensity.h | 10 +- common/include/pcl/common/intersections.h | 86 +- common/include/pcl/common/io.h | 44 + common/include/pcl/common/pca.h | 4 +- common/include/pcl/common/point_tests.h | 1 + common/include/pcl/common/random.h | 2 +- common/include/pcl/console/parse.h | 93 +- common/include/pcl/exceptions.h | 12 + common/include/pcl/impl/pcl_base.hpp | 2 +- common/include/pcl/impl/point_types.hpp | 211 +- common/include/pcl/pcl_base.h | 8 +- common/include/pcl/pcl_macros.h | 14 +- common/include/pcl/pcl_tests.h | 198 +- common/include/pcl/point_traits.h | 50 +- common/include/pcl/point_types.h | 100 + common/include/pcl/point_types_conversion.h | 22 +- .../pcl/range_image/bearing_angle_image.h | 89 + common/include/pcl/range_image/range_image.h | 1 - common/include/pcl/ros/conversions.h | 34 +- common/src/bearing_angle_image.cpp | 130 + common/src/intersections.cpp | 115 - common/src/io.cpp | 41 + common/src/parse.cpp | 16 +- common/src/pcl_base.cpp | 2 +- common/src/point_types.cpp | 7 + doc/CMakeLists.txt | 12 + doc/advanced/CMakeLists.txt | 14 + doc/advanced/Makefile | 6 - doc/advanced/content/_static/basic.css | 538 + doc/advanced/content/_static/sphinxdoc.css | 315 + doc/advanced/content/_templates/layout.html | 39 + doc/advanced/content/branches_repository.rst | 48 - doc/advanced/content/c_cache.rst | 2 +- doc/advanced/content/distcc.rst | 5 + .../content/files/PCL_eclipse_profile.xml | 91 +- .../content/how_to_write_a_tutorial.rst | 18 +- doc/advanced/content/index.rst | 31 +- doc/advanced/content/pcl2.rst | 4 +- doc/advanced/content/pcl_reg_eval.rst | 42 +- doc/advanced/content/pcl_registration.rst | 4 +- doc/advanced/content/pcl_style_guide.rst | 35 +- doc/advanced/content/vertical_sse.rst | 6 +- doc/doxygen/CMakeLists.txt | 21 +- doc/doxygen/doxyfile.in | 20 +- doc/doxygen/doxygen_layout.xml | 1 - doc/doxygen/pcl.doxy | 5 +- doc/overview/Makefile | 6 - doc/overview/content/_templates/layout.html | 8 - doc/overview/content/conf.py | 135 - doc/overview/content/index.rst | 35 - doc/tutorials/CMakeLists.txt | 20 +- doc/tutorials/Makefile | 6 - doc/tutorials/content/_static/basic.css | 538 + doc/tutorials/content/_static/sphinxdoc.css | 315 + doc/tutorials/content/_templates/layout.html | 39 + doc/tutorials/content/adding_custom_ptype.rst | 6 +- .../content/alignment_prerejective.rst | 26 +- doc/tutorials/content/bspline_fitting.rst | 278 + doc/tutorials/content/building_pcl.rst | 29 +- doc/tutorials/content/cloud_viewer.rst | 2 +- .../compiling_pcl_dependencies_windows.rst | 36 +- .../content/compiling_pcl_macosx.rst | 12 +- .../content/compiling_pcl_windows.rst | 39 +- .../content/correspondence_grouping.rst | 8 +- doc/tutorials/content/don_segmentation.rst | 3 - doc/tutorials/content/fpfh_estimation.rst | 2 +- doc/tutorials/content/generate_local_doc.rst | 74 + .../content/images/bspline_bunny.png | Bin 0 -> 85570 bytes .../content/images/eigen_vectors.png | Bin 0 -> 40600 bytes ...{ihs_lion_photo.JPG => ihs_lion_photo.jpg} | Bin .../images/interactive_icp/add_monkey.png | Bin 0 -> 35139 bytes .../images/interactive_icp/add_sub.png | Bin 0 -> 108203 bytes .../images/interactive_icp/animation.gif | Bin 0 -> 2247435 bytes .../images/interactive_icp/del_cube.png | Bin 0 -> 10984 bytes .../content/images/interactive_icp/export.png | Bin 0 -> 55056 bytes .../content/images/interactive_icp/icp-1.png | Bin 0 -> 465680 bytes .../content/images/interactive_icp/monkey.png | Bin 0 -> 34263 bytes .../content/images/interactive_icp/sub2.png | Bin 0 -> 20017 bytes .../content/images/matrix_transform/cube.png | Bin 0 -> 19748 bytes .../images/matrix_transform/cube_big.png | Bin 0 -> 167746 bytes .../content/images/moment_of_inertia.png | Bin 0 -> 29000 bytes .../images/pcl_with_eclipse/build_tab.gif | Bin 0 -> 577 bytes .../images/pcl_with_eclipse/eclipse.png | Bin 0 -> 4172 bytes .../images/pcl_with_eclipse/lrun_obj.gif | Bin 0 -> 379 bytes .../progressive_morphological_filter.png | Bin 0 -> 286644 bytes .../content/images/projected_cloud.png | Bin 0 -> 4791 bytes .../images/qt_visualizer/pcl_visualizer.gif | Bin 0 -> 162215 bytes .../content/images/qt_visualizer/qt.png | Bin 0 -> 6021 bytes .../images/qt_visualizer/qt_config.png | Bin 0 -> 110069 bytes .../content/images/qt_visualizer/ui.png | Bin 0 -> 43199 bytes doc/tutorials/content/images/rops_feature.png | Bin 0 -> 48837 bytes .../content/images/visualization/bunny.jpg | Bin .../content/images/visualization/ex1.jpg | Bin .../content/images/visualization/ex2.jpg | Bin .../content/images/visualization/ex3.jpg | Bin .../content/images/visualization/ex4.jpg | Bin .../content/images/visualization/ex5.jpg | Bin .../images/visualization/histogram.jpg | Bin .../content/images/visualization/normals.jpg | Bin .../content/images/visualization/pcs.jpg | Bin .../images/visualization/range_image.jpg | Bin .../content/images/visualization/shapes.jpg | Bin .../images/windows/SVNCheckout_pcl_trunk.png | Bin 29694 -> 0 bytes .../content/implicit_shape_model.rst | 14 +- doc/tutorials/content/in_hand_scanner.rst | 2 +- doc/tutorials/content/index.rst | 220 +- doc/tutorials/content/installing_homebrew.rst | 284 +- doc/tutorials/content/interactive_icp.rst | 282 + doc/tutorials/content/matrix_transform.rst | 185 + doc/tutorials/content/mobile_streaming.rst | 2 +- .../content/model_outlier_removal.rst | 81 + doc/tutorials/content/moment_of_inertia.rst | 119 + doc/tutorials/content/openni_grabber.rst | 2 +- .../pairwise_incremental_registration.rst | 13 +- doc/tutorials/content/pcl_plotter.rst | 6 +- doc/tutorials/content/pfh_estimation.rst | 4 +- doc/tutorials/content/planar_segmentation.rst | 2 +- .../progressive_morphological_filtering.rst | 129 + doc/tutorials/content/qt_visualizer.rst | 255 + .../content/region_growing_segmentation.rst | 4 +- doc/tutorials/content/rops_feature.rst | 114 + doc/tutorials/content/sources/CMakeLists.txt | 2 + .../alignment_prerejective/CMakeLists.txt | 2 +- .../alignment_prerejective.cpp | 13 +- .../sources/alignment_prerejective/chef.pcd | Bin 345723 -> 128513 bytes .../data/alignment_prerejective.tar.gz | Bin 4231720 -> 0 bytes .../sources/alignment_prerejective/rs1.pcd | Bin 10197328 -> 3531605 bytes .../content/sources/bare_earth/CMakeLists.txt | 12 + .../content/sources/bare_earth/bare_earth.cpp | 54 + .../sources/bspline_fitting/CMakeLists.txt | 13 + .../bspline_fitting/bspline_fitting.cpp | 219 + .../sources/iccv2011/include/load_clouds.h | 12 +- .../iccv2011/src/build_all_object_models.cpp | 2 +- .../iccv2011/src/build_object_model.cpp | 2 +- .../iccv2011/src/correspondence_viewer.cpp | 6 +- .../iccv2011/src/test_feature_estimation.cpp | 4 +- .../sources/iccv2011/src/test_filters.cpp | 8 +- .../iccv2011/src/test_object_recognition.cpp | 2 +- .../iccv2011/src/test_segmentation.cpp | 6 +- .../sources/iccv2011/src/test_surface.cpp | 2 +- .../sources/interactive_icp/CMakeLists.txt | 12 + .../interactive_icp/interactive_icp.cpp | 200 + .../sources/iros2011/include/load_clouds.h | 12 +- .../iros2011/src/build_all_object_models.cpp | 2 +- .../iros2011/src/build_object_model.cpp | 2 +- .../iros2011/src/correspondence_viewer.cpp | 6 +- .../iros2011/src/test_feature_estimation.cpp | 4 +- .../sources/iros2011/src/test_filters.cpp | 8 +- .../iros2011/src/test_object_recognition.cpp | 2 +- .../iros2011/src/test_segmentation.cpp | 6 +- .../sources/iros2011/src/test_surface.cpp | 2 +- .../sources/matrix_transform/CMakeLists.txt | 12 + .../matrix_transform/matrix_transform.cpp | 137 + .../model_outlier_removal/CMakeLists.txt | 12 + .../model_outlier_removal.cpp | 71 + .../sources/moment_of_inertia/CMakeLists.txt | 14 + .../moment_of_inertia/moment_of_inertia.cpp | 107 + .../narf_feature_extraction.cpp | 2 +- .../narf_keypoint_extraction.cpp | 2 +- .../normal_distributions_transform.cpp | 2 +- .../openni_narf_keypoint_extraction.cpp | 2 +- .../openni_range_image_visualization.cpp | 2 +- .../CMakeLists.txt | 1 - .../pairwise_incremental_registration.cpp | 2 +- .../planar_segmentation.cpp | 40 +- .../sources/qt_visualizer/CMakeLists.txt | 28 + .../content/sources/qt_visualizer/main.cpp | 12 + .../sources/qt_visualizer/pcl_visualizer.pro | 20 + .../qt_visualizer/pcl_visualizer.pro.user | 200 + .../sources/qt_visualizer/pclviewer.cpp | 121 + .../content/sources/qt_visualizer/pclviewer.h | 65 + .../sources/qt_visualizer/pclviewer.ui | 367 + .../random_sample_consensus.cpp | 2 +- .../range_image_border_extraction.cpp | 2 +- .../range_image_visualization.cpp | 2 +- .../region_growing_segmentation.cpp | 14 +- .../sources/registration_api/example2.cpp | 4 +- .../sources/rops_feature/CMakeLists.txt | 14 + .../sources/rops_feature/rops_feature.cpp | 64 + .../stick_segmentation/stick_segmentation.cpp | 2 +- .../vfh_recognition/nearest_neighbors.cpp | 2 +- .../content/supervoxel_clustering.rst | 8 +- doc/tutorials/content/template_alignment.rst | 4 +- .../content/using_kinfu_large_scale.rst | 4 +- .../content/using_pcl_with_eclipse.rst | 295 +- doc/tutorials/content/vfh_estimation.rst | 2 +- doc/tutorials/content/vfh_recognition.rst | 4 +- .../content/visualization.rst | 0 doc/tutorials/content/walkthrough.rst | 26 +- examples/keypoints/CMakeLists.txt | 3 + .../example_get_keypoints_indices.cpp | 82 + .../segmentation/example_region_growing.cpp | 8 +- examples/segmentation/example_supervoxels.cpp | 16 +- examples/surface/CMakeLists.txt | 4 + .../surface/example_nurbs_fitting_surface.cpp | 188 +- .../surface/example_nurbs_viewer_surface.cpp | 88 + features/CMakeLists.txt | 202 +- features/features.doxy | 6 +- features/include/pcl/features/3dsc.h | 10 +- features/include/pcl/features/cppf.h | 120 + features/include/pcl/features/cvfh.h | 1 + features/include/pcl/features/fpfh.h | 2 +- features/include/pcl/features/impl/cppf.hpp | 124 + features/include/pcl/features/impl/cvfh.hpp | 4 +- features/include/pcl/features/impl/esf.hpp | 1 - .../include/pcl/features/impl/feature.hpp | 6 +- .../features/impl/integral_image_normal.hpp | 184 +- .../pcl/features/impl/intensity_spin.hpp | 2 +- .../impl/moment_of_inertia_estimation.hpp | 649 + .../include/pcl/features/impl/our_cvfh.hpp | 25 +- features/include/pcl/features/impl/ppf.hpp | 10 +- features/include/pcl/features/impl/ppfrgb.hpp | 4 +- .../pcl/features/impl/rops_estimation.hpp | 537 + features/include/pcl/features/impl/shot.hpp | 1 + .../pcl/features/integral_image_normal.h | 31 +- .../include/pcl/features/intensity_gradient.h | 1 + .../features/moment_of_inertia_estimation.h | 362 + features/include/pcl/features/our_cvfh.h | 14 +- .../include/pcl/features/rops_estimation.h | 236 + features/include/pcl/features/shot.h | 1 - features/include/pcl/features/shot_lrf.h | 6 +- features/src/cppf.cpp | 128 + features/src/moment_of_inertia_estimation.cpp | 55 + features/src/pfh.cpp | 6 +- features/src/rops_estimation.cpp | 52 + features/src/shot.cpp | 2 + filters/CMakeLists.txt | 154 +- filters/include/pcl/filters/box_clipper3D.h | 6 +- filters/include/pcl/filters/clipper3D.h | 9 +- .../include/pcl/filters/conditional_removal.h | 4 +- filters/include/pcl/filters/convolution.h | 6 +- filters/include/pcl/filters/convolution_3d.h | 2 +- .../include/pcl/filters/covariance_sampling.h | 2 +- filters/include/pcl/filters/filter_indices.h | 10 + filters/include/pcl/filters/frustum_culling.h | 4 + filters/include/pcl/filters/grid_minimum.h | 137 + .../pcl/filters/impl/box_clipper3D.hpp | 4 +- .../pcl/filters/impl/conditional_removal.hpp | 10 +- .../include/pcl/filters/impl/convolution.hpp | 24 +- .../pcl/filters/impl/covariance_sampling.hpp | 6 +- .../include/pcl/filters/impl/grid_minimum.hpp | 198 + .../pcl/filters/impl/local_maximum.hpp | 191 + .../pcl/filters/impl/median_filter.hpp | 10 +- .../filters/impl/model_outlier_removal.hpp | 265 + .../pcl/filters/impl/morphological_filter.hpp | 208 + .../include/pcl/filters/impl/normal_space.hpp | 2 +- .../include/pcl/filters/impl/passthrough.hpp | 2 +- .../pcl/filters/impl/plane_clipper3D.hpp | 12 +- .../filters/impl/sampling_surface_normal.hpp | 6 +- .../include/pcl/filters/impl/voxel_grid.hpp | 37 +- filters/include/pcl/filters/local_maximum.h | 133 + .../pcl/filters/model_outlier_removal.h | 257 + .../pcl/filters/morphological_filter.h | 82 + filters/include/pcl/filters/plane_clipper3D.h | 6 +- .../pcl/filters/radius_outlier_removal.h | 2 +- filters/include/pcl/filters/shadowpoints.h | 2 +- .../pcl/filters/statistical_outlier_removal.h | 1 - filters/include/pcl/filters/voxel_grid.h | 34 +- .../pcl/filters/voxel_grid_covariance.h | 9 +- .../filters/voxel_grid_occlusion_estimation.h | 47 +- filters/src/grid_minimum.cpp | 52 + filters/src/local_maximum.cpp | 56 + filters/src/median_filter.cpp | 2 +- filters/src/model_outlier_removal.cpp | 51 + filters/src/morphological_filter.cpp | 52 + geometry/CMakeLists.txt | 55 +- geometry/include/pcl/geometry/mesh_base.h | 16 +- geometry/include/pcl/geometry/mesh_indices.h | 1 + geometry/include/pcl/geometry/mesh_traits.h | 10 +- .../include/pcl/geometry/polygon_operations.h | 1 + io/CMakeLists.txt | 260 +- .../impl/organized_pointcloud_compression.hpp | 5 +- io/include/pcl/compression/libpng_wrapper.h | 28 +- .../octree_pointcloud_compression.h | 4 +- .../organized_pointcloud_compression.h | 2 +- io/include/pcl/io/boost.h | 2 + io/include/pcl/io/dinast_grabber.h | 4 +- io/include/pcl/io/file_io.h | 73 + io/include/pcl/io/ifs_io.h | 258 + io/include/pcl/io/image.h | 215 + io/include/pcl/io/image_depth.h | 191 + io/include/pcl/io/image_grabber.h | 8 +- io/include/pcl/io/image_ir.h | 114 + io/include/pcl/io/image_metadata_wrapper.h | 83 + io/include/pcl/io/image_rgb24.h | 91 + io/include/pcl/io/image_yuv422.h | 79 + io/include/pcl/io/impl/lzf_image_io.hpp | 6 +- .../io/impl/point_cloud_image_extractors.hpp | 336 +- io/include/pcl/io/impl/vtk_lib_io.hpp | 3 +- io/include/pcl/io/io_exception.h | 107 + io/include/pcl/io/lzf_image_io.h | 19 +- io/include/pcl/io/obj_io.h | 286 +- io/include/pcl/io/openni2/openni.h | 87 + io/include/pcl/io/openni2/openni2_convert.h | 65 + io/include/pcl/io/openni2/openni2_device.h | 334 + .../pcl/io/openni2/openni2_device_info.h | 62 + .../pcl/io/openni2/openni2_device_manager.h | 102 + .../pcl/io/openni2/openni2_frame_listener.h | 89 + .../pcl/io/openni2/openni2_metadata_wrapper.h | 116 + .../pcl/io/openni2/openni2_timer_filter.h | 74 + .../pcl/io/openni2/openni2_video_mode.h | 93 + .../openni_shift_to_depth_conversion.h | 124 + io/include/pcl/io/openni2_grabber.h | 508 + .../pcl/io/openni_camera/openni_device.h | 3 + io/include/pcl/io/openni_grabber.h | 12 +- io/include/pcl/io/ply/ply_parser.h | 20 +- io/include/pcl/io/ply_io.h | 212 +- io/include/pcl/io/png_io.h | 66 +- .../pcl/io/point_cloud_image_extractors.h | 102 +- io/include/pcl/io/tar.h | 15 +- io/include/pcl/io/vtk_lib_io.h | 1 + io/src/ascii_io.cpp | 4 +- io/src/dinast_grabber.cpp | 12 +- io/src/file_io.cpp | 214 + io/src/ifs_io.cpp | 403 + io/src/image_depth.cpp | 302 + io/src/image_grabber.cpp | 16 +- io/src/image_ir.cpp | 160 + io/src/image_rgb24.cpp | 160 + io/src/image_yuv422.cpp | 160 + io/src/io_exception.cpp | 83 + io/src/libpng_wrapper.cpp | 4 +- io/src/lzf_image_io.cpp | 22 +- io/src/obj_io.cpp | 953 +- io/src/openni2/openni2_convert.cpp | 107 + io/src/openni2/openni2_device.cpp | 935 + io/src/openni2/openni2_device_info.cpp | 54 + io/src/openni2/openni2_device_manager.cpp | 266 + io/src/openni2/openni2_timer_filter.cpp | 98 + io/src/openni2/openni2_video_mode.cpp | 102 + io/src/openni2_grabber.cpp | 938 + io/src/openni_camera/openni_device.cpp | 2 +- io/src/openni_grabber.cpp | 73 +- io/src/pcd_grabber.cpp | 5 + io/src/pcd_io.cpp | 2 +- io/src/ply_io.cpp | 420 +- io/src/png_io.cpp | 51 + io/src/robot_eye_grabber.cpp | 2 +- io/src/vtk_lib_io.cpp | 30 +- io/tools/openni_pcd_recorder.cpp | 141 +- io/tools/ply/ply2obj.cpp | 4 +- io/tools/ply/ply2ply.cpp | 68 +- io/tools/ply/ply2raw.cpp | 4 +- kdtree/CMakeLists.txt | 32 +- kdtree/include/pcl/kdtree/impl/io.hpp | 10 +- .../include/pcl/kdtree/impl/kdtree_flann.hpp | 23 +- kdtree/include/pcl/kdtree/io.h | 12 +- kdtree/include/pcl/kdtree/kdtree.h | 13 +- kdtree/include/pcl/kdtree/kdtree_flann.h | 8 +- kdtree/kdtree.doxy | 2 +- keypoints/CMakeLists.txt | 58 +- keypoints/include/pcl/keypoints/agast_2d.h | 6 +- keypoints/include/pcl/keypoints/harris_2d.h | 12 +- keypoints/include/pcl/keypoints/harris_3d.h | 8 + keypoints/include/pcl/keypoints/harris_6d.h | 2 +- .../include/pcl/keypoints/impl/harris_2d.hpp | 96 +- .../include/pcl/keypoints/impl/harris_3d.hpp | 15 + .../include/pcl/keypoints/impl/harris_6d.hpp | 7 +- .../include/pcl/keypoints/impl/iss_3d.hpp | 17 +- .../include/pcl/keypoints/impl/keypoint.hpp | 3 + .../impl/smoothed_surfaces_keypoint.hpp | 5 +- .../include/pcl/keypoints/impl/susan.hpp | 15 +- .../pcl/keypoints/impl/trajkovic_2d.hpp | 257 + .../pcl/keypoints/impl/trajkovic_3d.hpp | 271 + keypoints/include/pcl/keypoints/iss_3d.h | 7 +- keypoints/include/pcl/keypoints/keypoint.h | 9 + .../keypoints/smoothed_surfaces_keypoint.h | 1 + keypoints/include/pcl/keypoints/susan.h | 5 +- .../include/pcl/keypoints/trajkovic_2d.h | 176 + .../include/pcl/keypoints/trajkovic_3d.h | 218 + keypoints/keypoints.doxy | 4 +- keypoints/src/agast_2d.cpp | 4 +- keypoints/src/narf_keypoint.cpp | 46 - keypoints/src/trajkovic_2d.cpp | 43 + keypoints/src/trajkovic_3d.cpp | 43 + octree/CMakeLists.txt | 72 +- .../pcl/octree/impl/octree_pointcloud.hpp | 45 +- .../impl/octree_pointcloud_adjacency.hpp | 117 +- .../include/pcl/octree/impl/octree_search.hpp | 21 +- octree/include/pcl/octree/octree2buf_base.h | 2 +- octree/include/pcl/octree/octree_container.h | 2 +- octree/include/pcl/octree/octree_iterator.h | 5 +- octree/include/pcl/octree/octree_nodes.h | 6 + .../pcl/octree/octree_pointcloud_adjacency.h | 361 +- .../octree_pointcloud_adjacency_container.h | 8 +- .../octree/octree_pointcloud_changedetector.h | 2 +- .../pcl/octree/octree_pointcloud_occupancy.h | 2 +- .../octree/octree_pointcloud_voxelcentroid.h | 5 +- octree/include/pcl/octree/octree_search.h | 4 + octree/octree.doxy | 2 +- octree/src/octree_inst.cpp | 16 +- outofcore/CMakeLists.txt | 92 +- outofcore/include/pcl/outofcore/octree_base.h | 44 +- .../include/pcl/outofcore/octree_base_node.h | 36 +- .../pcl/outofcore/octree_disk_container.h | 18 +- .../pcl/outofcore/octree_ram_container.h | 8 +- .../outofcore_breadth_first_iterator.h | 2 +- .../outofcore_depth_first_iterator.h | 2 +- .../pcl/outofcore/outofcore_iterator_base.h | 2 +- .../pcl/outofcore/visualization/axes.h | 11 +- .../outofcore/visualization/outofcore_cloud.h | 4 +- outofcore/src/visualization/camera.cpp | 2 +- outofcore/src/visualization/grid.cpp | 3 +- .../src/visualization/outofcore_cloud.cpp | 11 +- outofcore/src/visualization/scene.cpp | 6 +- outofcore/src/visualization/viewport.cpp | 8 +- outofcore/tools/CMakeLists.txt | 12 +- outofcore/tools/outofcore_print.cpp | 2 +- outofcore/tools/outofcore_viewer.cpp | 8 +- pcl_config.h.in | 10 + people/CMakeLists.txt | 50 +- .../main_ground_based_people_detection.cpp | 4 +- .../ground_based_people_detection_app.h | 131 +- .../pcl/people/head_based_subcluster.h | 4 +- .../ground_based_people_detection_app.hpp | 173 +- .../include/pcl/people/impl/height_map_2d.hpp | 4 +- .../pcl/people/impl/person_classifier.hpp | 26 +- people/include/pcl/people/person_cluster.h | 2 +- people/src/hog.cpp | 6 +- recognition/CMakeLists.txt | 211 +- .../include/pcl/recognition/cg/hough_3d.h | 15 +- .../pcl/recognition/color_gradient_modality.h | 6 +- .../include/pcl/recognition/crh_alignment.h | 10 +- recognition/include/pcl/recognition/dotmod.h | 8 +- .../pcl/recognition/hv/greedy_verification.h | 2 +- .../include/pcl/recognition/hv/hv_go.h | 2 +- .../include/pcl/recognition/impl/hv/hv_go.hpp | 6 + .../recognition/impl/implicit_shape_model.hpp | 8 +- .../recognition/impl/linemod/line_rgbd.hpp | 2 +- .../pcl/recognition/implicit_shape_model.h | 7 +- recognition/include/pcl/recognition/linemod.h | 7 + .../pcl/recognition/linemod/line_rgbd.h | 7 +- .../pcl/recognition/ransac_based/auxiliary.h | 9 +- .../recognition/ransac_based/model_library.h | 6 +- .../recognition/ransac_based/obj_rec_ransac.h | 8 +- .../pcl/recognition/surface_normal_modality.h | 19 +- recognition/src/hv/hv_go.cpp | 11 +- recognition/src/linemod.cpp | 24 + recognition/src/ransac_based/orr_octree.cpp | 10 +- registration/CMakeLists.txt | 213 +- .../registration/correspondence_estimation.h | 46 +- ...correspondence_estimation_backprojection.h | 37 + ...orrespondence_estimation_normal_shooting.h | 23 + ...pondence_estimation_organized_projection.h | 14 +- .../registration/correspondence_rejection.h | 56 +- .../correspondence_rejection_distance.h | 29 + .../correspondence_rejection_features.h | 4 +- ...correspondence_rejection_median_distance.h | 28 + ...respondence_rejection_organized_boundary.h | 28 + .../correspondence_rejection_poly.h | 30 +- ...orrespondence_rejection_sample_consensus.h | 52 +- .../correspondence_rejection_surface_normal.h | 69 +- .../correspondence_rejection_var_trimmed.h | 30 + registration/include/pcl/registration/elch.h | 3 +- registration/include/pcl/registration/gicp.h | 6 +- .../include/pcl/registration/gicp6d.h | 210 + .../include/pcl/registration/ia_ransac.h | 2 + registration/include/pcl/registration/icp.h | 9 +- .../impl/correspondence_estimation.hpp | 21 +- ...rrespondence_estimation_backprojection.hpp | 13 +- ...respondence_estimation_normal_shooting.hpp | 13 +- ...respondence_rejection_sample_consensus.hpp | 3 + .../include/pcl/registration/impl/elch.hpp | 1 + .../include/pcl/registration/impl/gicp.hpp | 3 +- .../pcl/registration/impl/ia_ransac.hpp | 4 +- .../include/pcl/registration/impl/icp.hpp | 87 +- .../pcl/registration/impl/joint_icp.hpp | 326 + .../registration/impl/ppf_registration.hpp | 28 +- .../pcl/registration/impl/registration.hpp | 29 +- .../impl/sample_consensus_prerejective.hpp | 136 +- .../impl/transformation_estimation_2D.hpp | 6 +- .../impl/transformation_estimation_dq.hpp | 6 +- ...nsformation_estimation_dual_quaternion.hpp | 6 +- .../impl/transformation_estimation_lm.hpp | 10 +- ...ormation_estimation_point_to_plane_lls.hpp | 9 +- ...estimation_point_to_plane_lls_weighted.hpp | 9 +- ...ion_estimation_point_to_plane_weighted.hpp | 16 +- .../impl/transformation_estimation_svd.hpp | 36 +- .../transformation_estimation_svd_scale.hpp | 2 +- .../include/pcl/registration/joint_icp.h | 233 + registration/include/pcl/registration/ndt.h | 2 +- .../include/pcl/registration/registration.h | 8 +- .../sample_consensus_prerejective.h | 13 +- .../transformation_estimation_lm.h | 8 +- ...sformation_estimation_point_to_plane_lls.h | 2 +- ...n_estimation_point_to_plane_lls_weighted.h | 3 +- ...ation_estimation_point_to_plane_weighted.h | 8 +- ...spondence_rejection_organized_boundary.cpp | 4 +- registration/src/gicp6d.cpp | 317 + registration/src/joint_icp.cpp | 39 + sample_consensus/CMakeLists.txt | 124 +- .../pcl/sample_consensus/impl/lmeds.hpp | 4 +- .../pcl/sample_consensus/impl/mlesac.hpp | 4 +- .../pcl/sample_consensus/impl/msac.hpp | 4 +- .../pcl/sample_consensus/impl/prosac.hpp | 2 +- .../pcl/sample_consensus/impl/ransac.hpp | 2 +- .../pcl/sample_consensus/impl/rmsac.hpp | 4 +- .../pcl/sample_consensus/impl/rransac.hpp | 2 +- .../impl/sac_model_circle.hpp | 12 +- .../impl/sac_model_circle3d.hpp | 14 +- .../sample_consensus/impl/sac_model_cone.hpp | 10 +- .../impl/sac_model_cylinder.hpp | 10 +- .../sample_consensus/impl/sac_model_line.hpp | 4 +- .../impl/sac_model_normal_parallel_plane.hpp | 133 +- .../impl/sac_model_normal_sphere.hpp | 2 +- .../impl/sac_model_parallel_line.hpp | 2 +- .../impl/sac_model_parallel_plane.hpp | 2 +- .../impl/sac_model_perpendicular_plane.hpp | 2 +- .../sample_consensus/impl/sac_model_plane.hpp | 16 +- .../impl/sac_model_registration.hpp | 8 +- .../impl/sac_model_registration_2d.hpp | 17 +- .../impl/sac_model_sphere.hpp | 10 +- .../sample_consensus/impl/sac_model_stick.hpp | 4 +- .../include/pcl/sample_consensus/sac.h | 4 +- .../include/pcl/sample_consensus/sac_model.h | 7 +- .../pcl/sample_consensus/sac_model_circle3d.h | 4 + .../pcl/sample_consensus/sac_model_line.h | 2 +- .../sac_model_normal_parallel_plane.h | 40 +- .../pcl/sample_consensus/sac_model_plane.h | 2 +- .../sample_consensus/sac_model_registration.h | 1 + .../sac_model_registration_2d.h | 8 +- .../pcl/sample_consensus/sac_model_sphere.h | 2 +- .../pcl/sample_consensus/sac_model_stick.h | 2 +- sample_consensus/sample_consensus.doxy | 28 +- search/CMakeLists.txt | 44 +- search/include/pcl/search/flann_search.h | 110 +- .../include/pcl/search/impl/flann_search.hpp | 18 +- search/include/pcl/search/impl/kdtree.hpp | 30 +- search/include/pcl/search/kdtree.h | 18 +- search/include/pcl/search/search.h | 13 +- segmentation/CMakeLists.txt | 120 +- ...oximate_progressive_morphological_filter.h | 178 + .../euclidean_cluster_comparator.h | 3 +- .../pcl/segmentation/extract_clusters.h | 10 +- .../{grabcut.h => grabcut_segmentation.h} | 204 +- ...imate_progressive_morphological_filter.hpp | 264 + .../impl/conditional_euclidean_clustering.hpp | 8 +- .../segmentation/impl/extract_clusters.hpp | 6 +- .../impl/extract_labeled_clusters.hpp | 2 +- .../impl/extract_polygonal_prism_data.hpp | 2 +- .../{grabcut.hpp => grabcut_segmentation.hpp} | 270 +- ...nized_connected_component_segmentation.hpp | 2 +- .../organized_multi_plane_segmentation.hpp | 2 +- .../impl/progressive_morphological_filter.hpp | 152 + .../pcl/segmentation/impl/region_growing.hpp | 32 +- .../segmentation/impl/region_growing_rgb.hpp | 34 +- .../impl/seeded_hue_segmentation.hpp | 4 +- .../segmentation/impl/segment_differences.hpp | 10 +- .../impl/supervoxel_clustering.hpp | 67 +- .../progressive_morphological_filter.h | 169 + .../include/pcl/segmentation/region_3d.h | 17 + .../include/pcl/segmentation/region_growing.h | 3 +- .../pcl/segmentation/region_growing_rgb.h | 1 + .../pcl/segmentation/sac_segmentation.h | 4 +- .../pcl/segmentation/supervoxel_clustering.h | 14 +- ...imate_progressive_morphological_filter.cpp | 53 + .../{grabcut.cpp => grabcut_segmentation.cpp} | 234 +- .../src/progressive_morphological_filter.cpp | 53 + segmentation/src/supervoxel_clustering.cpp | 5 + surface/CMakeLists.txt | 175 +- .../poisson4/multi_grid_octree_data.hpp | 18 +- .../pcl/surface/bilateral_upsampling.h | 6 + surface/include/pcl/surface/concave_hull.h | 6 +- surface/include/pcl/surface/ear_clipping.h | 9 +- .../pcl/surface/impl/bilateral_upsampling.hpp | 34 +- .../include/pcl/surface/impl/concave_hull.hpp | 2 +- .../include/pcl/surface/impl/convex_hull.hpp | 4 +- surface/include/pcl/surface/impl/gp3.hpp | 4 +- surface/include/pcl/surface/impl/mls.hpp | 34 +- .../pcl/surface/impl/texture_mapping.hpp | 25 +- surface/include/pcl/surface/mls.h | 20 +- surface/include/pcl/surface/poisson.h | 4 + surface/include/pcl/surface/texture_mapping.h | 46 +- .../vtk_mesh_quadric_decimation.h | 2 +- .../vtk_mesh_smoothing_laplacian.h | 2 +- .../vtk_mesh_smoothing_windowed_sinc.h | 2 +- .../pcl/surface/vtk_smoothing/vtk_utils.h | 2 + surface/src/ear_clipping.cpp | 113 +- surface/src/on_nurbs/sequential_fitter.cpp | 4 +- .../vtk_mesh_quadric_decimation.cpp | 5 + .../vtk_mesh_smoothing_laplacian.cpp | 5 + .../vtk_mesh_smoothing_windowed_sinc.cpp | 5 + .../vtk_smoothing/vtk_mesh_subdivision.cpp | 5 + surface/src/vtk_smoothing/vtk_utils.cpp | 5 + surface/surface.doxy | 2 +- test/CMakeLists.txt | 43 +- test/common/CMakeLists.txt | 3 + test/common/test_centroid.cpp | 1001 + test/common/test_common.cpp | 812 +- test/common/test_copy_make_borders.cpp | 171 + test/common/test_copy_point.cpp | 188 + test/common/test_eigen.cpp | 335 +- test/common/test_io.cpp | 144 +- test/common/test_plane_intersection.cpp | 410 +- test/features/CMakeLists.txt | 38 +- test/features/test_base_feature.cpp | 4 +- test/features/test_cppf_estimation.cpp | 131 + .../test_moment_of_inertia_estimation.cpp | 129 + test/features/test_rops_estimation.cpp | 169 + test/filters/CMakeLists.txt | 21 +- test/filters/test_filters.cpp | 15 +- test/filters/test_grid_minimum.cpp | 89 + test/filters/test_local_maximum.cpp | 84 + test/filters/test_model_outlier_removal.cpp | 105 + test/filters/test_morphological.cpp | 169 + test/geometry/test_mesh_circulators.cpp | 6 +- test/geometry/test_mesh_conversion.cpp | 2 +- .../include/gtest/gtest-death-test.h | 283 - .../gtest-1.6.0/include/gtest/gtest-message.h | 230 - .../include/gtest/gtest-param-test.h | 1421 - .../include/gtest/gtest-printers.h | 796 - test/gtest-1.6.0/include/gtest/gtest-spi.h | 232 - .../include/gtest/gtest-test-part.h | 176 - .../include/gtest/gtest-typed-test.h | 259 - test/gtest-1.6.0/include/gtest/gtest.h | 2159 - .../include/gtest/gtest_pred_impl.h | 358 - test/gtest-1.6.0/include/gtest/gtest_prod.h | 58 - .../internal/gtest-death-test-internal.h | 308 - .../include/gtest/internal/gtest-filepath.h | 210 - .../include/gtest/internal/gtest-internal.h | 1226 - .../include/gtest/internal/gtest-linked_ptr.h | 233 - .../internal/gtest-param-util-generated.h | 4822 -- .../include/gtest/internal/gtest-param-util.h | 619 - .../include/gtest/internal/gtest-port.h | 1775 - .../include/gtest/internal/gtest-string.h | 350 - .../include/gtest/internal/gtest-tuple.h | 968 - .../include/gtest/internal/gtest-type-util.h | 3330 - test/gtest-1.6.0/src/gtest-all.cc | 48 - test/gtest-1.6.0/src/gtest-death-test.cc | 1238 - test/gtest-1.6.0/src/gtest-filepath.cc | 380 - test/gtest-1.6.0/src/gtest-internal-inl.h | 1038 - test/gtest-1.6.0/src/gtest-port.cc | 746 - test/gtest-1.6.0/src/gtest-printers.cc | 356 - test/gtest-1.6.0/src/gtest-test-part.cc | 110 - test/gtest-1.6.0/src/gtest-typed-test.cc | 110 - test/gtest-1.6.0/src/gtest.cc | 4898 -- test/gtest-1.6.0/src/gtest_main.cc | 39 - test/io/CMakeLists.txt | 4 +- test/io/test_grabbers.cpp | 8 +- test/io/test_ply_mesh_io.cpp | 238 +- test/io/test_point_cloud_image_extractors.cpp | 74 + test/kdtree/CMakeLists.txt | 2 +- test/keypoints/CMakeLists.txt | 4 +- test/lamppost.pcd | 1782 + test/outofcore/CMakeLists.txt | 2 +- test/outofcore/test_outofcore.cpp | 32 +- test/registration/CMakeLists.txt | 6 +- test/registration/test_registration.cpp | 204 +- test/registration/test_registration_api.cpp | 8 +- test/rops_cloud.pcd | 32098 +++++++++ test/rops_indices.txt | 1000 + test/rops_triangles.txt | 57619 ++++++++++++++++ test/sac_plane_test.pcd | 6579 +- test/sample_consensus/CMakeLists.txt | 16 + .../test_sample_consensus.cpp | 139 + .../test_sample_consensus_line_model.cpp | 115 + .../test_sample_consensus_plane_models.cpp | 334 + .../test_sample_consensus_quadric_models.cpp | 538 + test/search/test_flann_search.cpp | 3 +- test/surface/CMakeLists.txt | 18 +- test/surface/test_ear_clipping.cpp | 73 + test/test_bearing_angle_image.cpp | 94 + ...t_people_groundBasedPeopleDetectionApp.cpp | 6 +- ...est_recognition_ransac_based_ORROctree.cpp | 147 + test/test_sample_consensus.cpp | 976 - test/test_transforms.cpp | 2 +- tools/CMakeLists.txt | 178 +- tools/compute_hausdorff.cpp | 161 + tools/compute_hull.cpp | 4 +- tools/concatenate_points_pcd.cpp | 2 +- tools/fast_bilateral_filter.cpp | 2 +- tools/generate.cpp | 212 + tools/gp3_surface.cpp | 4 +- tools/grid_min.cpp | 222 + tools/linemod_detection.cpp | 2 +- tools/local_max.cpp | 223 + tools/lum.cpp | 4 +- tools/match_linemod_template.cpp | 2 +- tools/mesh2pcd.cpp | 4 +- tools/mesh_sampling.cpp | 8 +- tools/morph.cpp | 247 + tools/normal_estimation.cpp | 2 +- tools/obj2pcd.cpp | 137 + tools/obj2vtk.cpp | 6 +- tools/obj_rec_ransac_accepted_hypotheses.cpp | 9 + tools/obj_rec_ransac_hash_table.cpp | 2 +- tools/obj_rec_ransac_model_opps.cpp | 5 + tools/obj_rec_ransac_orr_octree.cpp | 9 + .../obj_rec_ransac_orr_octree_zprojection.cpp | 21 + tools/obj_rec_ransac_result.cpp | 11 +- tools/obj_rec_ransac_scene_opps.cpp | 5 + tools/octree_viewer.cpp | 12 +- tools/oni2pcd.cpp | 2 +- tools/outlier_removal.cpp | 6 +- tools/pcd2png.cpp | 85 +- tools/pcd_change_viewpoint.cpp | 2 +- tools/ply2pcd.cpp | 2 +- tools/ply2vtk.cpp | 8 +- tools/png2pcd.cpp | 483 +- tools/progressive_morphological_filter.cpp | 325 + tools/radius_filter.cpp | 3 +- tools/sac_segmentation_plane.cpp | 2 +- tools/tiff2pcd.cpp | 6 +- tools/transform_point_cloud.cpp | 8 +- tools/virtual_scanner.cpp | 4 +- tools/voxel_grid.cpp | 2 +- tools/voxel_grid_occlusion_estimation.cpp | 20 +- tools/vtk2pcd.cpp | 4 + tools/vtk2ply.cpp | 8 +- tracking/CMakeLists.txt | 72 +- tracking/include/pcl/tracking/coherence.h | 2 +- .../pcl/tracking/impl/hsv_color_coherence.hpp | 14 +- .../pcl/tracking/impl/pyramidal_klt.hpp | 645 + .../nearest_pair_point_cloud_coherence.h | 2 +- .../include/pcl/tracking/particle_filter.h | 2 +- tracking/include/pcl/tracking/pyramidal_klt.h | 377 + tracking/include/pcl/tracking/tracker.h | 2 +- visualization/CMakeLists.txt | 144 +- .../pcl/visualization/area_picking_event.h | 6 +- .../pcl/visualization/common/actor_map.h | 3 +- .../pcl/visualization/common/impl/shapes.hpp | 2 - .../include/pcl/visualization/common/shapes.h | 24 +- .../pcl/visualization/histogram_visualizer.h | 4 +- .../include/pcl/visualization/image_viewer.h | 31 +- .../impl/histogram_visualizer.hpp | 4 +- .../pcl/visualization/impl/image_viewer.hpp | 11 +- .../pcl/visualization/impl/pcl_visualizer.hpp | 75 +- .../impl/point_cloud_color_handlers.hpp | 210 +- .../impl/registration_visualizer.hpp | 2 +- .../include/pcl/visualization/interactor.h | 12 +- .../pcl/visualization/interactor_style.h | 85 +- .../include/pcl/visualization/pcl_painter2D.h | 12 +- .../include/pcl/visualization/pcl_plotter.h | 27 +- .../pcl/visualization/pcl_visualizer.h | 165 +- .../point_cloud_color_handlers.h | 105 + .../pcl/visualization/point_picking_event.h | 13 +- .../pcl/visualization/vtk/pcl_context_item.h | 12 + .../include/pcl/visualization/window.h | 4 +- visualization/src/cloud_viewer.cpp | 2 +- visualization/src/common/io.cpp | 5 + visualization/src/common/shapes.cpp | 21 +- visualization/src/histogram_visualizer.cpp | 6 + visualization/src/image_viewer.cpp | 107 +- visualization/src/interactor_style.cpp | 355 +- visualization/src/pcl_painter2D.cpp | 2 - visualization/src/pcl_plotter.cpp | 34 +- visualization/src/pcl_visualizer.cpp | 873 +- visualization/src/point_cloud_handlers.cpp | 88 +- visualization/src/point_picking_event.cpp | 3 +- visualization/src/vtk/pcl_context_item.cpp | 32 + .../src/vtk/vtkVertexBufferObject.cxx | 1 - .../src/vtk/vtkVertexBufferObjectMapper.cxx | 9 + visualization/test/test_shapes.cpp | 8 +- visualization/tools/CMakeLists.txt | 4 + visualization/tools/hdl_viewer_simple.cpp | 11 +- visualization/tools/image_grabber_viewer.cpp | 2 +- visualization/tools/openni2_viewer.cpp | 370 + visualization/tools/pcd_grabber_viewer.cpp | 2 +- visualization/tools/pcd_viewer.cpp | 21 +- visualization/visualization.doxy | 2 +- 837 files changed, 139042 insertions(+), 42158 deletions(-) create mode 100755 .travis.sh create mode 100644 CONTRIBUTING.md mode change 100755 => 100644 apps/modeler/CMakeLists.txt create mode 100644 apps/src/grabcut_2d.cpp create mode 100644 apps/src/ni_trajkovic.cpp create mode 100644 apps/src/openni_klt.cpp create mode 100644 cmake/Modules/FindGtest.cmake delete mode 100644 cmake/Modules/FindMPI.cmake create mode 100644 cmake/Modules/FindOpenNI2.cmake create mode 100644 cmake/pcl_find_gl.cmake create mode 100644 common/include/pcl/common/copy_point.h create mode 100644 common/include/pcl/common/impl/accumulators.hpp create mode 100644 common/include/pcl/common/impl/copy_point.hpp create mode 100644 common/include/pcl/common/impl/intersections.hpp create mode 100644 common/include/pcl/range_image/bearing_angle_image.h create mode 100644 common/src/bearing_angle_image.cpp delete mode 100644 common/src/intersections.cpp create mode 100644 doc/advanced/CMakeLists.txt delete mode 100644 doc/advanced/Makefile create mode 100644 doc/advanced/content/_static/basic.css create mode 100644 doc/advanced/content/_static/sphinxdoc.css delete mode 100644 doc/advanced/content/branches_repository.rst delete mode 100644 doc/overview/Makefile delete mode 100644 doc/overview/content/_templates/layout.html delete mode 100644 doc/overview/content/conf.py delete mode 100644 doc/overview/content/index.rst delete mode 100644 doc/tutorials/Makefile create mode 100644 doc/tutorials/content/_static/basic.css create mode 100644 doc/tutorials/content/_static/sphinxdoc.css create mode 100644 doc/tutorials/content/bspline_fitting.rst create mode 100644 doc/tutorials/content/generate_local_doc.rst create mode 100644 doc/tutorials/content/images/bspline_bunny.png create mode 100644 doc/tutorials/content/images/eigen_vectors.png rename doc/tutorials/content/images/{ihs_lion_photo.JPG => ihs_lion_photo.jpg} (100%) create mode 100644 doc/tutorials/content/images/interactive_icp/add_monkey.png create mode 100644 doc/tutorials/content/images/interactive_icp/add_sub.png create mode 100644 doc/tutorials/content/images/interactive_icp/animation.gif create mode 100644 doc/tutorials/content/images/interactive_icp/del_cube.png create mode 100644 doc/tutorials/content/images/interactive_icp/export.png create mode 100644 doc/tutorials/content/images/interactive_icp/icp-1.png create mode 100644 doc/tutorials/content/images/interactive_icp/monkey.png create mode 100644 doc/tutorials/content/images/interactive_icp/sub2.png create mode 100644 doc/tutorials/content/images/matrix_transform/cube.png create mode 100644 doc/tutorials/content/images/matrix_transform/cube_big.png create mode 100644 doc/tutorials/content/images/moment_of_inertia.png create mode 100644 doc/tutorials/content/images/pcl_with_eclipse/build_tab.gif create mode 100644 doc/tutorials/content/images/pcl_with_eclipse/eclipse.png create mode 100644 doc/tutorials/content/images/pcl_with_eclipse/lrun_obj.gif create mode 100644 doc/tutorials/content/images/progressive_morphological_filter.png create mode 100644 doc/tutorials/content/images/projected_cloud.png create mode 100644 doc/tutorials/content/images/qt_visualizer/pcl_visualizer.gif create mode 100644 doc/tutorials/content/images/qt_visualizer/qt.png create mode 100644 doc/tutorials/content/images/qt_visualizer/qt_config.png create mode 100644 doc/tutorials/content/images/qt_visualizer/ui.png create mode 100644 doc/tutorials/content/images/rops_feature.png rename doc/{overview => tutorials}/content/images/visualization/bunny.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/ex1.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/ex2.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/ex3.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/ex4.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/ex5.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/histogram.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/normals.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/pcs.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/range_image.jpg (100%) rename doc/{overview => tutorials}/content/images/visualization/shapes.jpg (100%) delete mode 100644 doc/tutorials/content/images/windows/SVNCheckout_pcl_trunk.png create mode 100644 doc/tutorials/content/interactive_icp.rst create mode 100644 doc/tutorials/content/matrix_transform.rst create mode 100644 doc/tutorials/content/model_outlier_removal.rst create mode 100644 doc/tutorials/content/moment_of_inertia.rst create mode 100644 doc/tutorials/content/progressive_morphological_filtering.rst create mode 100644 doc/tutorials/content/qt_visualizer.rst create mode 100644 doc/tutorials/content/rops_feature.rst delete mode 100644 doc/tutorials/content/sources/alignment_prerejective/data/alignment_prerejective.tar.gz create mode 100644 doc/tutorials/content/sources/bare_earth/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/bare_earth/bare_earth.cpp create mode 100644 doc/tutorials/content/sources/bspline_fitting/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/bspline_fitting/bspline_fitting.cpp create mode 100644 doc/tutorials/content/sources/interactive_icp/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/interactive_icp/interactive_icp.cpp create mode 100644 doc/tutorials/content/sources/matrix_transform/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/matrix_transform/matrix_transform.cpp create mode 100644 doc/tutorials/content/sources/model_outlier_removal/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/model_outlier_removal/model_outlier_removal.cpp create mode 100644 doc/tutorials/content/sources/moment_of_inertia/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/moment_of_inertia/moment_of_inertia.cpp create mode 100644 doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/qt_visualizer/main.cpp create mode 100644 doc/tutorials/content/sources/qt_visualizer/pcl_visualizer.pro create mode 100644 doc/tutorials/content/sources/qt_visualizer/pcl_visualizer.pro.user create mode 100644 doc/tutorials/content/sources/qt_visualizer/pclviewer.cpp create mode 100644 doc/tutorials/content/sources/qt_visualizer/pclviewer.h create mode 100644 doc/tutorials/content/sources/qt_visualizer/pclviewer.ui create mode 100644 doc/tutorials/content/sources/rops_feature/CMakeLists.txt create mode 100644 doc/tutorials/content/sources/rops_feature/rops_feature.cpp rename doc/{overview => tutorials}/content/visualization.rst (100%) create mode 100644 examples/keypoints/example_get_keypoints_indices.cpp create mode 100644 examples/surface/example_nurbs_viewer_surface.cpp create mode 100755 features/include/pcl/features/cppf.h create mode 100755 features/include/pcl/features/impl/cppf.hpp create mode 100644 features/include/pcl/features/impl/moment_of_inertia_estimation.hpp create mode 100644 features/include/pcl/features/impl/rops_estimation.hpp create mode 100644 features/include/pcl/features/moment_of_inertia_estimation.h create mode 100644 features/include/pcl/features/rops_estimation.h create mode 100755 features/src/cppf.cpp create mode 100644 features/src/moment_of_inertia_estimation.cpp create mode 100644 features/src/rops_estimation.cpp create mode 100644 filters/include/pcl/filters/grid_minimum.h create mode 100644 filters/include/pcl/filters/impl/grid_minimum.hpp create mode 100644 filters/include/pcl/filters/impl/local_maximum.hpp create mode 100644 filters/include/pcl/filters/impl/model_outlier_removal.hpp create mode 100644 filters/include/pcl/filters/impl/morphological_filter.hpp create mode 100644 filters/include/pcl/filters/local_maximum.h create mode 100644 filters/include/pcl/filters/model_outlier_removal.h create mode 100644 filters/include/pcl/filters/morphological_filter.h create mode 100644 filters/src/grid_minimum.cpp create mode 100644 filters/src/local_maximum.cpp create mode 100644 filters/src/model_outlier_removal.cpp create mode 100644 filters/src/morphological_filter.cpp create mode 100644 io/include/pcl/io/ifs_io.h create mode 100644 io/include/pcl/io/image.h create mode 100644 io/include/pcl/io/image_depth.h create mode 100644 io/include/pcl/io/image_ir.h create mode 100644 io/include/pcl/io/image_metadata_wrapper.h create mode 100644 io/include/pcl/io/image_rgb24.h create mode 100644 io/include/pcl/io/image_yuv422.h create mode 100644 io/include/pcl/io/io_exception.h create mode 100644 io/include/pcl/io/openni2/openni.h create mode 100644 io/include/pcl/io/openni2/openni2_convert.h create mode 100644 io/include/pcl/io/openni2/openni2_device.h create mode 100644 io/include/pcl/io/openni2/openni2_device_info.h create mode 100644 io/include/pcl/io/openni2/openni2_device_manager.h create mode 100644 io/include/pcl/io/openni2/openni2_frame_listener.h create mode 100644 io/include/pcl/io/openni2/openni2_metadata_wrapper.h create mode 100644 io/include/pcl/io/openni2/openni2_timer_filter.h create mode 100644 io/include/pcl/io/openni2/openni2_video_mode.h create mode 100644 io/include/pcl/io/openni2/openni_shift_to_depth_conversion.h create mode 100644 io/include/pcl/io/openni2_grabber.h create mode 100644 io/src/file_io.cpp create mode 100644 io/src/ifs_io.cpp create mode 100644 io/src/image_depth.cpp create mode 100644 io/src/image_ir.cpp create mode 100644 io/src/image_rgb24.cpp create mode 100644 io/src/image_yuv422.cpp create mode 100644 io/src/io_exception.cpp create mode 100644 io/src/openni2/openni2_convert.cpp create mode 100644 io/src/openni2/openni2_device.cpp create mode 100644 io/src/openni2/openni2_device_info.cpp create mode 100644 io/src/openni2/openni2_device_manager.cpp create mode 100644 io/src/openni2/openni2_timer_filter.cpp create mode 100644 io/src/openni2/openni2_video_mode.cpp create mode 100644 io/src/openni2_grabber.cpp create mode 100644 keypoints/include/pcl/keypoints/impl/trajkovic_2d.hpp create mode 100644 keypoints/include/pcl/keypoints/impl/trajkovic_3d.hpp create mode 100644 keypoints/include/pcl/keypoints/trajkovic_2d.h create mode 100644 keypoints/include/pcl/keypoints/trajkovic_3d.h create mode 100644 keypoints/src/trajkovic_2d.cpp create mode 100644 keypoints/src/trajkovic_3d.cpp create mode 100644 registration/include/pcl/registration/gicp6d.h create mode 100644 registration/include/pcl/registration/impl/joint_icp.hpp create mode 100644 registration/include/pcl/registration/joint_icp.h create mode 100644 registration/src/gicp6d.cpp create mode 100644 registration/src/joint_icp.cpp create mode 100644 segmentation/include/pcl/segmentation/approximate_progressive_morphological_filter.h rename segmentation/include/pcl/segmentation/{grabcut.h => grabcut_segmentation.h} (86%) create mode 100644 segmentation/include/pcl/segmentation/impl/approximate_progressive_morphological_filter.hpp rename segmentation/include/pcl/segmentation/impl/{grabcut.hpp => grabcut_segmentation.hpp} (61%) create mode 100644 segmentation/include/pcl/segmentation/impl/progressive_morphological_filter.hpp create mode 100644 segmentation/include/pcl/segmentation/progressive_morphological_filter.h create mode 100644 segmentation/src/approximate_progressive_morphological_filter.cpp rename segmentation/src/{grabcut.cpp => grabcut_segmentation.cpp} (91%) create mode 100644 segmentation/src/progressive_morphological_filter.cpp create mode 100644 test/common/test_centroid.cpp create mode 100644 test/common/test_copy_make_borders.cpp create mode 100644 test/common/test_copy_point.cpp create mode 100755 test/features/test_cppf_estimation.cpp create mode 100644 test/features/test_moment_of_inertia_estimation.cpp create mode 100644 test/features/test_rops_estimation.cpp create mode 100644 test/filters/test_grid_minimum.cpp create mode 100644 test/filters/test_local_maximum.cpp create mode 100644 test/filters/test_model_outlier_removal.cpp create mode 100644 test/filters/test_morphological.cpp delete mode 100644 test/gtest-1.6.0/include/gtest/gtest-death-test.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest-message.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest-param-test.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest-printers.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest-spi.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest-test-part.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest-typed-test.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest_pred_impl.h delete mode 100644 test/gtest-1.6.0/include/gtest/gtest_prod.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-death-test-internal.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-filepath.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-internal.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-linked_ptr.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-param-util-generated.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-param-util.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-port.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-string.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-tuple.h delete mode 100644 test/gtest-1.6.0/include/gtest/internal/gtest-type-util.h delete mode 100644 test/gtest-1.6.0/src/gtest-all.cc delete mode 100644 test/gtest-1.6.0/src/gtest-death-test.cc delete mode 100644 test/gtest-1.6.0/src/gtest-filepath.cc delete mode 100644 test/gtest-1.6.0/src/gtest-internal-inl.h delete mode 100644 test/gtest-1.6.0/src/gtest-port.cc delete mode 100644 test/gtest-1.6.0/src/gtest-printers.cc delete mode 100644 test/gtest-1.6.0/src/gtest-test-part.cc delete mode 100644 test/gtest-1.6.0/src/gtest-typed-test.cc delete mode 100644 test/gtest-1.6.0/src/gtest.cc delete mode 100644 test/gtest-1.6.0/src/gtest_main.cc create mode 100644 test/lamppost.pcd create mode 100644 test/rops_cloud.pcd create mode 100644 test/rops_indices.txt create mode 100644 test/rops_triangles.txt create mode 100644 test/sample_consensus/CMakeLists.txt create mode 100644 test/sample_consensus/test_sample_consensus.cpp create mode 100644 test/sample_consensus/test_sample_consensus_line_model.cpp create mode 100644 test/sample_consensus/test_sample_consensus_plane_models.cpp create mode 100644 test/sample_consensus/test_sample_consensus_quadric_models.cpp create mode 100644 test/test_bearing_angle_image.cpp create mode 100644 test/test_recognition_ransac_based_ORROctree.cpp delete mode 100644 test/test_sample_consensus.cpp create mode 100644 tools/compute_hausdorff.cpp create mode 100644 tools/generate.cpp create mode 100644 tools/grid_min.cpp create mode 100644 tools/local_max.cpp create mode 100644 tools/morph.cpp create mode 100644 tools/obj2pcd.cpp create mode 100644 tools/progressive_morphological_filter.cpp create mode 100644 tracking/include/pcl/tracking/impl/pyramidal_klt.hpp create mode 100644 tracking/include/pcl/tracking/pyramidal_klt.h create mode 100644 visualization/tools/openni2_viewer.cpp diff --git a/.travis.sh b/.travis.sh new file mode 100755 index 00000000..cba0e050 --- /dev/null +++ b/.travis.sh @@ -0,0 +1,135 @@ +#!/bin/sh + +PCL_DIR=`pwd` +BUILD_DIR=$PCL_DIR/build +DOC_DIR=$BUILD_DIR/doc/doxygen/html + +TUTORIALS_DIR=$BUILD_DIR/doc/tutorials/html +ADVANCED_DIR=$BUILD_DIR/doc/advanced/html + +CMAKE_C_FLAGS="-Wall -Wextra -Wabi -O2" +CMAKE_CXX_FLAGS="-Wall -Wextra -Wabi -O2" + +function build () +{ + case $CC in + clang ) build_clang;; + gcc ) build_gcc;; + esac +} + +function build_clang () +{ + # A complete build + # Configure + mkdir $BUILD_DIR && cd $BUILD_DIR + cmake -DCMAKE_C_FLAGS=$CMAKE_C_FLAGS -DCMAKE_CXX_FLAGS=$CMAKE_CXX_FLAGS \ + -DPCL_ONLY_CORE_POINT_TYPES=ON \ + -DBUILD_global_tests=OFF \ + $PCL_DIR + # Build + make -j2 +} + +function build_gcc () +{ + # A reduced build, only pcl_common + # Configure + mkdir $BUILD_DIR && cd $BUILD_DIR + cmake -DCMAKE_C_FLAGS=$CMAKE_C_FLAGS -DCMAKE_CXX_FLAGS=$CMAKE_CXX_FLAGS \ + -DPCL_ONLY_CORE_POINT_TYPES=ON \ + -DBUILD_2d=OFF \ + -DBUILD_features=OFF \ + -DBUILD_filters=OFF \ + -DBUILD_geometry=OFF \ + -DBUILD_global_tests=OFF \ + -DBUILD_io=OFF \ + -DBUILD_kdtree=OFF \ + -DBUILD_keypoints=OFF \ + -DBUILD_ml=OFF \ + -DBUILD_octree=OFF \ + -DBUILD_outofcore=OFF \ + -DBUILD_people=OFF \ + -DBUILD_recognition=OFF \ + -DBUILD_registration=OFF \ + -DBUILD_sample_consensus=OFF \ + -DBUILD_search=OFF \ + -DBUILD_segmentation=OFF \ + -DBUILD_stereo=OFF \ + -DBUILD_surface=OFF \ + -DBUILD_tools=OFF \ + -DBUILD_tracking=OFF \ + -DBUILD_visualization=OFF \ + $PCL_DIR + # Build + make -j2 +} + +function test () +{ + # Configure + mkdir $BUILD_DIR && cd $BUILD_DIR + cmake -DCMAKE_C_FLAGS=$CMAKE_C_FLAGS -DCMAKE_CXX_FLAGS=$CMAKE_CXX_FLAGS -DPCL_ONLY_CORE_POINT_TYPES=ON -DBUILD_global_tests=ON -DPCL_NO_PRECOMPILE=ON $PCL_DIR + # Build and run tests + make pcl_filters -j3 + make test_filters + make pcl_registration -j3 + make test_registration + make test_registration_api + make tests -j3 +} + +function doc () +{ + # Do not generate documentation for pull requests + if [[ $TRAVIS_PULL_REQUEST != 'false' ]]; then exit; fi + # Install doxygen and sphinx + sudo apt-get install doxygen doxygen-latex graphviz python-pip + sudo pip install sphinx sphinxcontrib-doxylink + # Configure + mkdir $BUILD_DIR && cd $BUILD_DIR + cmake -DDOXYGEN_USE_SHORT_NAMES=OFF \ + -DSPHINX_HTML_FILE_SUFFIX=php \ + -DWITH_DOCS=1 \ + -DWITH_TUTORIALS=1 \ + $PCL_DIR + + git config --global user.email "documentation@pointclouds.org" + git config --global user.name "PointCloudLibrary (via TravisCI)" + + if [ -z "$id_rsa_{1..23}" ]; then echo 'No $id_rsa_{1..23} found !' ; exit 1; fi + + echo -n $id_rsa_{1..23} >> ~/.ssh/travis_rsa_64 + base64 --decode --ignore-garbage ~/.ssh/travis_rsa_64 > ~/.ssh/id_rsa + + chmod 600 ~/.ssh/id_rsa + + echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + + cd $DOC_DIR + git clone git@github.com:PointCloudLibrary/documentation.git . + + # Generate documentation and tutorials + cd $BUILD_DIR + make doc tutorials advanced + + # Upload to GitHub if generation succeeded + if [[ $? == 0 ]]; then + # Copy generated tutorials to the doc directory + cp -r $TUTORIALS_DIR/* $DOC_DIR/tutorials + cp -r $ADVANCED_DIR/* $DOC_DIR/advanced + # Commit and push + cd $DOC_DIR + git add --all + git commit --amend -m "Documentation for commit $TRAVIS_COMMIT" + git push --force + else + exit 2 + fi +} + +case $TASK in + build ) build;; + test ) test;; + doc ) doc;; +esac diff --git a/.travis.yml b/.travis.yml index 5abd127d..f2562b5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,45 @@ language: cpp compiler: - gcc - clang +env: + matrix: + - TASK="build" + global: + - secure: XQw5SBf/7b1SHFR+kKklBWhWVgNvm4vIi+wwyajFSbDLOPpsAqtnDKeA2DV9ciaQJ3CVAvBoyxYgzAvpbsb5k95jadbvu9aSlo/AQnAbz+8DhkJL25DwJAn8G4s4zD1MFi7P4fxJHZsv/l9UcdW4BzjEhh0VidWCO4hP6I9BAQc= + - secure: dRKTSeQI2Jad+/K9XCkNZxuu8exPi2wGzf6D0ogd1Nb2ZIUsOtnHSME4DO+xv7F5ZYrythHTrfezQl5hhcK+cr7A12okxlvmF/gVFuGCBPkUbyWPOrxx/Ic5pqdVnmrMFG1hFmr1KmOxCVx0F48JfGNd4ZgtUBAmnIomRp8sXRI= + - secure: ah6/Y0D8bBFfAU38RdWsLJ/0Gp5uN5KEHVOnyhEUx1wDaBcDl9+aIE9Xyah44ei/fqQg1MXBfgMnaF7oHpDs4dAKITYP4wV8WDX1DCl1dalIrWMTSFYRknc3Y6hT+HadMlkcV9CCLEhZ7gyyNkm+idbekt/WbQE6Jls/vBhdZxI= + - secure: V8XIEPjagHSFInXjogs8ypsC/gL5dq4VENYZbC9q8KYrNT9y1DLnMgNh9pGad25OjOqftBFwsgx6QYo357+MwpynfF+KcYNybjuR/vVGXpLcm0Uytnp6bE7oQbQ1s806TlXHb0Xk/bO2cLRYCCMCkhUOm+Dreu1uhKpoI/z0VMs= + - secure: vPRheiXkGnzBHRaVFsA3VtwK6DtWG48VIdbOxboaR6jb9jT9yNz5EQrapiLOFFkhGsZ1mCgeunR58BGUPiSl8gEvOheBBUgZW6x8kbHDpxSUc2H70bLRAKxP4t8e3ZDFg2RjGnvXkGhzUTu9oWnbfWxGAILJAOpNoT0MqDgP+Z0= + - secure: bT9kXekVN89zJeS4IEobLOeuAmRJqsgTjZky/mGqmOY1H8oIgcHC+41twB+nxkaU2mQskOvG45UwnAAW/8X6WdTbwKYeFWI5mXpCiXoiGL/dsYiig3GzYYv32ZJQL9B8tkEW6Xc0GY6v4K91Xw+HoKLi/tjxh3NjQxpfktwwCBQ= + - secure: kp5CTFyo/E5+v382ypD1mIP7RIVOq5A1NDur1NrYI9or+8+zGcK5A2/Ex6Bb6rac5l7cVcqx6Xel+clxH2eQP2D8GqkaxdZs/u9L7MdFqsfn/QYOIshYlowRoLX86W0KOhsTdLLv2mOS6DnWhIuhgDfrczD3hFQdP9PMTBpd65A= + - secure: YXJJRdv5OD/Qo1vNqPnFfx//SotxecFQyXjzEKQ8Zxu+EfVKVs95DUiUX+hiDlPrVGKhI3kTvza+lkaIv9fkjWiwSja5LsUbW/+2cwkhoHmOzVtdcpascfP7fcXc0kWTuvg1FLGNBv26SEym1FfNzp0Sm+ANZsCc4fQVXjDhQSY= + - secure: wyWnJoZydXcFW359Vid6YfG9l0WTFqIpuEhgFV8gtSbkrSU0JrrUrKuN5ld/cPb+sRa/I8FAftSDsH4CW67impwLmfNfGf4wZTOBvBKyDGjlI+TLEo4ew/yq+MYIkkEleCWOj5eUkAHPHUUhJzI8SvX+ZuxiJEXapoV0xymbrig= + - secure: vCvNI8egL2DRCicbWTuLOyXiW8478tedYvRneDMtCDB2lYToG32sYY0fS9KIciNohgObC8dbVraScgobL5cL4Ir4qrTUfBvGJ71OOMVujNEvkTts4YyI5zhA1PeEJ9+xcbQkE0/f78g7HQnd2LjZLXSxxrFVyJnjGaq1siNNRik= + - secure: iUjKlT1bJq3pZp3tS0yOmycSZwmGSbrfTe9fWs0P78o3WRYlzBx4IWa+RZb1l0l6LpCUo00wdgeKKhvzClHFza31fumZJKkFeDf/jxAM2TtSbcIxxXwqpi4yJJZs7SkYrU/lugv0NI6UHtl5wAkIp8sjtCCHVYJjlYNHaLhL75o= + - secure: DWrK3JsbzV5iUK3Xj6MpVWwlZv85GxdLl8c73ONcynZJ1tzUU3bfdvOtMxJrAnmH9QANw5RGORgbOyiDnvydCCpmL9RjswFqfkQX0mRTV8UYDPlJ1bBZJkX8I97yw8W1UyK1Q76kfr5bZjhikpsS/81Ll6z6Kj9FOte6KFfbznk= + - secure: B32G/fehtPQdu1bF+dbCJ/Eo22MiszxZj7UOwNggRFifoxTmRdffZyuqapW0PLCTbBEvlS6UfajGOmVvZx5QH8Q/gtutJqXDTMgWpOai66JUwnpn6AX6NnhFGc+s2cpp3V2+5I26OrFkaXTcS7flz32XJdKZmPgvjY1qoppmyzo= + - secure: u0cyLpY3LVF1gA8Sj4Q7X4Xv4bBT7m8IBDnm/AS412H0dM47dcFu8uxVFgWRu3WrM8T87Uc7+ftHkxKJezXgDPEVUixAnwLg2nEVEf6v3HC/HW+X9m98q1mELKXTLxc/f57rAIhhYPkjQh+leg6JmrhG1t0X7kh7d3CY0wwdSL0= + - secure: KlIjQVEWlr+H/PAKIAcKS6WO1EFBdXXvXLisEnferB1RWgGwuLRgtIZzI+BJdt/7BMSyWvRExqt6xNyfqpxKXl1kdJawc3rpeYufklHQgmB2qGBSrpMtNr0S3gPFePBdnETbdPHwA63QCrpRKcrHqJxmeIzAmstH736iRXuubFs= + - secure: ldwk79cqSgaEUZLt5rbNLRcNaVf/bx2zjBEDbvzAF9JCqVx/L5zCRTr5raHsxzBOzz25Qs3nFW81e1WLwxMAWshvI7EM/YG8GXqECvJGWpHBwcZI1SVP3zMhpH/jJE8vbMFaM2NOmhMT03z91vt0NlvR4DJMY0KV351awGSL2Do= + - secure: SyLCwwc+jjkdmNUkRdGRDR2lNrPCu1ZvPstvVWQke5uw3BlnVKXWK7V3yq9g11ZsCl/7aldBexjf7pqeXbJ5Wl5goiI3E+/Ooujd/EWkMn9K3YlG57p8Zdw/A/fUMJgAH3qrM//ihdO0KDJD8eCGLlm4qV0SnlWFPQ+Dy8BsAc8= + - secure: DaqjsZS60Y070Gw2lUNltzDltiYKB8IlYqsp0SyOjZAKlDGgp97+9YGEaIGcKF1qw3VGswg+7rrjWQ59iiwstTqgvx1mTTik0Qc0RCc8GtvIm+PS9TOhWxQginmhZmET9QKnGB7uj6K63qN8V8MZakZWIJxgUXx8jGiCTD22/eQ= + - secure: x4x3vHY6Wf4kxjAT8dbWRl8n4PxTGv8RtzfGIZYXvJgbnY2qW+cJ8Edp64V1LegvQbBQmKqAP9YSLHwZsuL3LxfVqt/seRs+DJMDVUd9jVYmym0rPqemJLezapalEg6qfLuoeNkDPWvIVccQCDEBPfaUdD0ZXYo44LS5jIV0+T8= + - secure: Pm2hyxdSLnY3ltrAva0FwNWWEQQcnf1JK2Fhjc3sWFpStMF7Obk93u4G5M6f2f28ZY6HFaMRYC1qEz/+yMIjsusIv8j0E6hgB/EnoM0dlxCc0aryH3X2IOYBVjRMjOFPmhYbNBoMmZWLluHWSyVSqr9k9nxowMfM3mi4fah11aQ= + - secure: WTZ238yAEfXRyll1n8yau3FUW9HTvq6scKIl9AmNZrnzTr9dktupWrBVV6CtvaufT1mSmDigZ7VGC6T71HkyRIyb2qfVTrnjnxE96Wtcci6PfkuQc2L2puuZYo8dXaBRoOgJKGHFo/uKVKWnp7t55dp3lBJJmclHhon+K2hMSJw= + - secure: LNsNoBvqY/jYDoBjWCE5cM+f1H8xOwSBc/tbWZo6E/jPRjUOLzXSicMMUMrlVto+bFzSUT8OVajV3XmoRx+Qntzv6bDSAGjdycvHd2YZQPn8BYrsFtR4So7SsJkF9FlxzbiOXaiSRpwGn7TP/DO7Neubrr4IS2ef4nWowGrnCE8= + - secure: PZivWbaCWFA2BFFY8n3UMxdEWjz7rBh568u9LF5LH3HgWADnfiwWzNriACqX9fhe7tSmDru5Bk978s+xPPAY9v24cfiDEX5a5MQ/XVr2rP48n3vlUDWERDhIodJ73F9F9GGZXToGdNz0MBUAHgiv7Lb0GYUfmOYzUJjWghngLBw= +matrix: + include: + - compiler: clang + env: TASK="test" + - env: TASK="doc" before_install: - sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl -y - sudo add-apt-repository ppa:apokluda/boost1.53 -y + - sudo add-apt-repository ppa:yade-users/external -y + - sudo add-apt-repository ppa:libreoffice/ppa -y - sudo apt-get update -d - - sudo apt-get install cmake libvtk5-qt4-dev libflann-dev libeigen3-dev libopenni-dev libqhull-dev libboost-filesystem1.53-dev libboost-iostreams1.53-dev libboost-thread1.53-dev -script: - - mkdir build && cd build - - cmake -DBUILD_global_tests=ON -DCMAKE_C_FLAGS="-Wall -Wextra -Wabi -O2" -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wabi -O2" -DPCL_ONLY_CORE_POINT_TYPES=ON .. && make -j2 && make test +install: + - sudo apt-get install libvtk5-qt4-dev libflann-dev libeigen3-dev libopenni-dev libqhull-dev libboost-filesystem1.53-dev libboost-iostreams1.53-dev libboost-thread1.53-dev libboost-chrono1.53-dev libusb-1.0-0-dev libgtest-dev +script: + - bash .travis.sh diff --git a/CHANGES.md b/CHANGES.md index 68f33564..adc8e4ef 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,285 @@ # ChangeList +## *= 1.7.2 (10.09.2014) =* + +* Added support for VTK6 + [[#363]](https://github.com/PointCloudLibrary/pcl/pull/363) +* Removed Google Test from the source tree and added it as a system dependency + [[#731]](https://github.com/PointCloudLibrary/pcl/pull/731) +* Added support for QHull 2012 on non-Debian platforms + [[#852]](https://github.com/PointCloudLibrary/pcl/pull/852) + +### `libpcl_common:` + +* Added `BearingAngleImage` class + [[#198]](https://github.com/PointCloudLibrary/pcl/pull/198) +* Added `pcl::CPPFSignature` point type + [[#296]](https://github.com/PointCloudLibrary/pcl/pull/296) +* Added `getRGBAVector4i()`, `getBGRVector3cMap()`, and `getBGRAVector4cMap()` + to all point types containing RGB/RGBA fields + [[#450]](https://github.com/PointCloudLibrary/pcl/pull/450) +* Added a family of "has field" functions to check presence of a particular + field in a point type both at compile- and run-time + [[#462]](https://github.com/PointCloudLibrary/pcl/pull/462) +* Added a function to copy data between points of different types + [[#465]](https://github.com/PointCloudLibrary/pcl/pull/465) +* Added test macros for equality/nearness checks + [[#499]](https://github.com/PointCloudLibrary/pcl/pull/499) +* Added `descriptorSize()` to all point types with descriptors + [[#531]](https://github.com/PointCloudLibrary/pcl/pull/531) +* Added possibility to copy a cloud inside another one while interpolating + borders + [[#567]](https://github.com/PointCloudLibrary/pcl/pull/567) +* Added a function to determine the point of intersection of three non-parallel + planes + [[#571]](https://github.com/PointCloudLibrary/pcl/pull/571) +* Fixed a bug in HSV to RGB color conversion + [[#581]](https://github.com/PointCloudLibrary/pcl/pull/581) +* Added a new `CentroidPoint` class + [[#586]](https://github.com/PointCloudLibrary/pcl/pull/586) +* Templated intersection computation functions on scalar type + [[#646]](https://github.com/PointCloudLibrary/pcl/pull/646) +* Templated functions in 'eigen.h' on scalar type + [[#660]](https://github.com/PointCloudLibrary/pcl/pull/660) +* Added functions to transform points, vectors, lines, etc. + [[#660]](https://github.com/PointCloudLibrary/pcl/pull/660) + +### `libpcl_features:` + +* Added a simple implementation of CPPF using normalised HSV values in the + feature vector + [[#296]](https://github.com/PointCloudLibrary/pcl/pull/296) +* Added `MomentOfInertiaEstimation` and `ROPSEstimation` features + [[#319]](https://github.com/PointCloudLibrary/pcl/pull/319) +* Fixed a problem in `OURCVFHEstimation::computeRFAndShapeDistribution()` + [[#738]](https://github.com/PointCloudLibrary/pcl/pull/738) +* Fixed undefined behavior in `OURCVFHEstimation::computeFeature()` + [[#811]](https://github.com/PointCloudLibrary/pcl/pull/811) +* Fixed memory corruption error in OUR-CVFH + [[#875]](https://github.com/PointCloudLibrary/pcl/pull/875) + +### `libpcl_filters:` + +* Added a function to set the minimum number of points required for a voxel to + be used in `VoxelGrid` + [[#434]](https://github.com/PointCloudLibrary/pcl/pull/434) +* Added `GridMinimum` filter + [[#520]](https://github.com/PointCloudLibrary/pcl/pull/520) +* Added a morphological filter that operates on Z dimension + [[#533]](https://github.com/PointCloudLibrary/pcl/pull/533) +* Added progressive morphological filter to extract ground returns + [[#574]](https://github.com/PointCloudLibrary/pcl/pull/574) +* Added a filter to remove locally maximal points in the z dimension + [[#577]](https://github.com/PointCloudLibrary/pcl/pull/577) +* Added an approximate version of the progressive morphological filter + [[#665]](https://github.com/PointCloudLibrary/pcl/pull/665) +* Added `ModelOutlierRemoval` class that filters points in a cloud based on the + distance between model and point + [[#702]](https://github.com/PointCloudLibrary/pcl/pull/702) + +### `libpcl_io:` + +* Added experimental version of an OpenNI 2.x grabber + [[#276]](https://github.com/PointCloudLibrary/pcl/pull/276) + [[#843]](https://github.com/PointCloudLibrary/pcl/pull/843) +* Added support for IFS file format + [[#354]](https://github.com/PointCloudLibrary/pcl/pull/354) + [[#356]](https://github.com/PointCloudLibrary/pcl/pull/356) +* Added possibility to load `PCLPointCloud2` from OBJ files + [[#363]](https://github.com/PointCloudLibrary/pcl/pull/363) +* Fixed loading and saving of PLY files + [[#510]](https://github.com/PointCloudLibrary/pcl/pull/510) + [[#579]](https://github.com/PointCloudLibrary/pcl/pull/579) +* Fixed race conditions in `PCDGrabber` + [[#582]](https://github.com/PointCloudLibrary/pcl/pull/582) +* Fixed multi openni grabber buffer corruption + [[#845]](https://github.com/PointCloudLibrary/pcl/pull/845) +* Fixed incompatibility with Boost 1.56 in `LZFImageWriter` + [[#867]](https://github.com/PointCloudLibrary/pcl/pull/867) +* Fixed a bug in `PLYReader` which lead to deformation of point clouds when + displayed in `CloudViewer` or `PCLVisualizer` + [[#879]](https://github.com/PointCloudLibrary/pcl/pull/879) + +### `libpcl_kdtree:` + +* Fixed double memory free bug in `KdTreeFLANN` + [[#618]](https://github.com/PointCloudLibrary/pcl/pull/618) + +### `libpcl_keypoints:` + +* Added a method `Keypoint::getKeypointsIndices ()` + [[#318]](https://github.com/PointCloudLibrary/pcl/pull/318) +* Added keypoints based on Trajkovic and Hedley operator (2D and 3D versions) + [[#409]](https://github.com/PointCloudLibrary/pcl/pull/409) + +### `libpcl_octree:` + +* Fixed a bug in `OctreePointCloudAdjacency::computeNeighbors()` + [[#455]](https://github.com/PointCloudLibrary/pcl/pull/455) +* Accelerated `OctreePointCloudAdjacency` building by disabling dynamic key + resizing + [[#332]](https://github.com/PointCloudLibrary/pcl/pull/332) +* Fixed a bug with infinite points in `OctreePointCloudAdjacency` + [[#723]](https://github.com/PointCloudLibrary/pcl/pull/723) + +### `libpcl_people:` + +* Added a possibility to define a transformation matrix for people tracker + [[#606]](https://github.com/PointCloudLibrary/pcl/pull/606) + +### `libpcl_recognition:` + +* Allow PCL to be built against a system-wide installed metslib + [[#299]](https://github.com/PointCloudLibrary/pcl/pull/299) +* Fixed a bug in `ObjRecRANSAC::addModel()` + [[#269]](https://github.com/PointCloudLibrary/pcl/pull/269) +* Added `LINEMOD::loadTemplates()` (useful for object recognition systems that + store templates for different objects in different files) + [[#358]](https://github.com/PointCloudLibrary/pcl/pull/358) + +### `libpcl_registration:` + +* Fixed `SampleConsensusInitialAlignment::hasConverged()` + [[#339]](https://github.com/PointCloudLibrary/pcl/pull/339) +* Added `JointIterativeClosestPoint` + [[#344]](https://github.com/PointCloudLibrary/pcl/pull/344) +* Made correspondence rejectors to actually work with ICP + [[#419]](https://github.com/PointCloudLibrary/pcl/pull/419) +* Added `GeneralizedIterativeClosestPoint6D` that integrates Lab color space + information into the GICP algorithm + [[#491]](https://github.com/PointCloudLibrary/pcl/pull/491) +* Fixed bugs and optimized `SampleConsensusPrerejective` + [[#741]](https://github.com/PointCloudLibrary/pcl/pull/741) +* Fixed a bug in `TransformationEstimationSVDScale` + [[#885]](https://github.com/PointCloudLibrary/pcl/pull/885) + +### `libpcl_sample_consensus:` + +* Unified `SampleConsensusModelNormalParallelPlane` with + `SampleConsensusModelNormalPlane` to avoid code duplication + [[#696]](https://github.com/PointCloudLibrary/pcl/pull/696) + +### `libpcl_search:` + +* `search::KdTree` can now be used with different KdTree implementations + [[#81]](https://github.com/PointCloudLibrary/pcl/pull/81) +* Added a new interface to FLANN's multiple randomized trees for + high-dimensional (feature) searches + [[#435]](https://github.com/PointCloudLibrary/pcl/pull/435) +* Fixed a bug in the `Ptr` typdef in `KdTree` + [[#820]](https://github.com/PointCloudLibrary/pcl/pull/820) + +### `libpcl_segmentation:` + +* Added `GrabCut` segmentation and a show-case application for 2D + [[#330]](https://github.com/PointCloudLibrary/pcl/pull/330) +* Updated `RegionGrowingRGB::assembleRegion()` to speed up the algorithm + [[#538]](https://github.com/PointCloudLibrary/pcl/pull/538) +* Fixed a bug with missing point infinity test in `RegionGrowing` + [[#617]](https://github.com/PointCloudLibrary/pcl/pull/617) +* Fixed alignment issue in `SupervoxelClustering` + [[#625]](https://github.com/PointCloudLibrary/pcl/pull/625) +* Added a curvature parameter to `Region3D` class + [[#653]](https://github.com/PointCloudLibrary/pcl/pull/653) +* Fixed a minor bug in `OrganizedConnectedComponentSegmentation` + [[#802]](https://github.com/PointCloudLibrary/pcl/pull/802) + +### `libpcl_surface:` + +* Fixed a bug in `EarClipping` where computation failed if all vertices have + the same x or y component + [[#130]](https://github.com/PointCloudLibrary/pcl/pull/130) +* Added support for unequal focal lengths along different axes in texture + mapping + [[#352]](https://github.com/PointCloudLibrary/pcl/pull/352) +* Speeded up bilateral upsampling + [[#689]](https://github.com/PointCloudLibrary/pcl/pull/689) +* Reduced space usage in `MovingLeastSquares` + [[#785]](https://github.com/PointCloudLibrary/pcl/pull/785) + +### `libpcl_tracking:` + +* Fixed Hue distance calculation in tracking `HSVColorCoherence` + [[#390]](https://github.com/PointCloudLibrary/pcl/pull/390) +* Added pyramidal KLT tracking + [[#587]](https://github.com/PointCloudLibrary/pcl/pull/587) + +### `libpcl_visualization:` + +* Added a new color handler `PointCloudColorHandlerRGBAField` that takes into + account alpha channel + [[#306]](https://github.com/PointCloudLibrary/pcl/pull/306) +* Fixed `PCLVisualizer` crashes on OS X + [[#384]](https://github.com/PointCloudLibrary/pcl/pull/384) +* Added possibility to display texture on polygon meshes + [[#400]](https://github.com/PointCloudLibrary/pcl/pull/400) +* Added ability to add and remove several coordinate systems + [[#401]](https://github.com/PointCloudLibrary/pcl/pull/401) +* Added `ImageViewer::markPoints()` + [[#439]](https://github.com/PointCloudLibrary/pcl/pull/439) +* Added `setWindowPosition()` and `setWindowName()` to `PCLPlotter` + [[#457]](https://github.com/PointCloudLibrary/pcl/pull/457) +* Changed camera parameters display to be more user-friendly + [[#544]](https://github.com/PointCloudLibrary/pcl/pull/544) +* Added `PCLVisualizer::updateCoordinateSystemPose()` + [[#569]](https://github.com/PointCloudLibrary/pcl/pull/569) +* Fixed display of non-triangular meshes in `PCLVisualizer` + [[#686]](https://github.com/PointCloudLibrary/pcl/pull/686) +* Added a capability to save and restore camera view in `PCLVisualizer` + [[#703]](https://github.com/PointCloudLibrary/pcl/pull/703) +* Added `PCLVisualizer::getShapeActorMap()` function + [[#725]](https://github.com/PointCloudLibrary/pcl/pull/725) +* Fixed undefined behavior when drawing axis in `PCLVisualizer` + [[#762]](https://github.com/PointCloudLibrary/pcl/pull/762) +* Fixed HSV to RGB conversion in `PointCloudColorHandlerHSVField` + [[#772]](https://github.com/PointCloudLibrary/pcl/pull/772) +* Fixed non-working key presses in visualization GUIs on Mac OS X systems + [[#795]](https://github.com/PointCloudLibrary/pcl/pull/795) +* Fixed a bug in `PCLVisualizer::addCube()` + [[#846]](https://github.com/PointCloudLibrary/pcl/pull/846) +* Fixed a bug in cone visualization and added possibility to set cone length + [[#881]](https://github.com/PointCloudLibrary/pcl/pull/881) + +### `PCL Tools:` + +* Added a simple tool to compute Hausdorff distance between two point clouds + [[#519]](https://github.com/PointCloudLibrary/pcl/pull/519) +* Updated `pcl_viewer` to use RGB color handler as default + [[#556]](https://github.com/PointCloudLibrary/pcl/pull/556) +* Added a morphological tool `pcl_morph` to apply dilate/erode/open/close + operations on the Z dimension + [[#572]](https://github.com/PointCloudLibrary/pcl/pull/572) +* Added a tool `pcl_generate` to generate random clouds + [[#599]](https://github.com/PointCloudLibrary/pcl/pull/599) +* Added a tool `pcl_grid_min` to find grid minimums + [[#603]](https://github.com/PointCloudLibrary/pcl/pull/603) +* Added a tool `pcl_local_max` to filter out local maxima + [[#604]](https://github.com/PointCloudLibrary/pcl/pull/604) +* Added optional depth image input to `pcl_png2pcd` converter + [[#680]](https://github.com/PointCloudLibrary/pcl/pull/680) +* Fixed memory size calculation in `pcl_openni_pcd_recorder` + [[#676]](https://github.com/PointCloudLibrary/pcl/pull/676) +* Added device ID parameter to `pcl_openni_pcd_recorder` + [[#673]](https://github.com/PointCloudLibrary/pcl/pull/673) +* Added automatic camera reset on startup in `pcl_viewer` + [[#693]](https://github.com/PointCloudLibrary/pcl/pull/693) +* Added a capability to save and restore camera view in `pcl_viewer` + [[#703]](https://github.com/PointCloudLibrary/pcl/pull/703) +* Updated `pcl_pcd2png` tool to be able to paint pixels corresponding to + infinite points with black. Added Glasbey lookup table to paint labels with + a fixed set of highly distinctive colors. + [[#767]](https://github.com/PointCloudLibrary/pcl/pull/767) +* Added `pcl_obj2pcd` tool + [[#816]](https://github.com/PointCloudLibrary/pcl/pull/816) + +### `PCL Apps:` + +* Fixed disappearing cloud from selection in Cloud Composer + [[#814]](https://github.com/PointCloudLibrary/pcl/pull/814) + + ## *= 1.7.1 (07.10.2013) =* + * New pcl::io::savePNGFile() functions and pcd2png tool (deprecates organized_pcd_to_png). * Support for Intel Perceptual Computing SDK cameras. * New Dual quaternion transformation estimation algorithm. diff --git a/CMakeLists.txt b/CMakeLists.txt index f2196da1..f0a56003 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,10 @@ ### ---[ PCL global CMake cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +if(POLICY CMP0048) + cmake_policy(SET CMP0048 OLD) # do not use VERSION option in project() command +endif() + set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "possible configurations" FORCE) # In case the user does not setup CMAKE_BUILD_TYPE, assume it's RelWithDebInfo @@ -12,7 +16,10 @@ project(PCL) string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) ### ---[ Find universal dependencies -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/" ${CMAKE_MODULE_PATH}) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/" ${CMAKE_MODULE_PATH}) + +# ---[ Include pkgconfig +include (FindPkgConfig) # ---[ Release/Debug specific flags if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") @@ -25,6 +32,12 @@ if(WIN32 AND NOT MINGW) if(NOT DEFINED CMAKE_RELEASE_POSTFIX) set(CMAKE_RELEASE_POSTFIX "_release") endif() + if(NOT DEFINED CMAKE_RELWITHDEBINFO_POSTFIX) + set(CMAKE_RELWITHDEBINFO_POSTFIX "_release") + endif() + if(NOT DEFINED CMAKE_MINSIZEREL_POSTFIX) + set(CMAKE_MINSIZEREL_POSTFIX "_release") + endif() endif() # ---[ special maintainer mode @@ -58,9 +71,9 @@ if (ANDROID) message ("PCL shared libs on Android must be: ${PCL_SHARED_LIBS}") endif() -include(${PCL_SOURCE_DIR}/cmake/pcl_verbosity.cmake) -include(${PCL_SOURCE_DIR}/cmake/pcl_targets.cmake) -include(${PCL_SOURCE_DIR}/cmake/pcl_options.cmake) +include("${PCL_SOURCE_DIR}/cmake/pcl_verbosity.cmake") +include("${PCL_SOURCE_DIR}/cmake/pcl_targets.cmake") +include("${PCL_SOURCE_DIR}/cmake/pcl_options.cmake") # Enable verbose timing display? if(CMAKE_TIMING_VERBOSE AND UNIX) @@ -69,7 +82,7 @@ if(CMAKE_TIMING_VERBOSE AND UNIX) endif(CMAKE_TIMING_VERBOSE AND UNIX) # check for SSE flags -include(${PCL_SOURCE_DIR}/cmake/pcl_find_sse.cmake) +include("${PCL_SOURCE_DIR}/cmake/pcl_find_sse.cmake") if (PCL_ENABLE_SSE) PCL_CHECK_FOR_SSE() endif (PCL_ENABLE_SSE) @@ -145,33 +158,29 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") SET(CMAKE_C_FLAGS "-Qunused-arguments") endif() if("${CMAKE_CXX_FLAGS}" STREQUAL "") - SET(CMAKE_CXX_FLAGS "-Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args + SET(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args + if(APPLE AND WITH_CUDA AND CUDA_FOUND) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") + endif() endif() SET(CLANG_LIBRARIES "stdc++") endif() -# ---[ Project folders -option(USE_PROJECT_FOLDERS "Use folders to organize PCL projects in an IDE." OFF) -mark_as_advanced(USE_PROJECT_FOLDERS) -if(USE_PROJECT_FOLDERS) - set_property(GLOBAL PROPERTY USE_FOLDERS ON) -endif(USE_PROJECT_FOLDERS) - -include(${PCL_SOURCE_DIR}/cmake/pcl_utils.cmake) -set(PCL_VERSION 1.7.1 CACHE STRING "PCL version") +include("${PCL_SOURCE_DIR}/cmake/pcl_utils.cmake") +set(PCL_VERSION 1.7.2 CACHE STRING "PCL version") DISSECT_VERSION() GET_OS_INFO() SET_INSTALL_DIRS() if(WIN32) - set(PCL_RESOURCES_DIR ${PCL_SOURCE_DIR}/resources) - set(PCL_POINTCLOUDS_DIR ${PCL_RESOURCES_DIR}/pointclouds) + set(PCL_RESOURCES_DIR "${PCL_SOURCE_DIR}/resources") + set(PCL_POINTCLOUDS_DIR "${PCL_RESOURCES_DIR}/pointclouds") endif(WIN32) -set(PCL_OUTPUT_LIB_DIR ${PCL_BINARY_DIR}/${LIB_INSTALL_DIR}) -set(PCL_OUTPUT_BIN_DIR ${PCL_BINARY_DIR}/${BIN_INSTALL_DIR}) -make_directory(${PCL_OUTPUT_LIB_DIR}) -make_directory(${PCL_OUTPUT_BIN_DIR}) +set(PCL_OUTPUT_LIB_DIR "${PCL_BINARY_DIR}/${LIB_INSTALL_DIR}") +set(PCL_OUTPUT_BIN_DIR "${PCL_BINARY_DIR}/${BIN_INSTALL_DIR}") +make_directory("${PCL_OUTPUT_LIB_DIR}") +make_directory("${PCL_OUTPUT_BIN_DIR}") if(WIN32) foreach(config ${CMAKE_CONFIGURATION_TYPES}) string(TOUPPER ${config} CONFIG) @@ -207,7 +216,7 @@ ENDIF("${is_system_dir}" STREQUAL "-1") ### ---[ Find universal dependencies # the gcc-4.2.1 coming with MacOS X is not compatible with the OpenMP pragmas we use, so disabling OpenMP for it -if((NOT APPLE) OR (NOT CMAKE_COMPILER_IS_GNUCXX) OR (GCC_VERSION VERSION_GREATER 4.2.1)) +if((NOT APPLE) OR (NOT CMAKE_COMPILER_IS_GNUCXX) OR (GCC_VERSION VERSION_GREATER 4.2.1) OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) find_package(OpenMP) endif() if(OPENMP_FOUND) @@ -227,7 +236,7 @@ else(OPENMP_FOUND) message (STATUS "Not found OpenMP") endif() # Boost (required) -include(${PCL_SOURCE_DIR}/cmake/pcl_find_boost.cmake) +include("${PCL_SOURCE_DIR}/cmake/pcl_find_boost.cmake") # Eigen (required) find_package(Eigen REQUIRED) include_directories(SYSTEM ${EIGEN_INCLUDE_DIRS}) @@ -241,121 +250,177 @@ find_package(FLANN 1.7.0 REQUIRED) include_directories(${FLANN_INCLUDE_DIRS}) # libusb-1.0 -find_package(libusb-1.0) -if(LIBUSB_1_FOUND) - include_directories(${LIBUSB_1_INCLUDE_DIR}) -endif(LIBUSB_1_FOUND) +option(WITH_LIBUSB "Build USB RGBD-Camera drivers" TRUE) +if(WITH_LIBUSB) + find_package(libusb-1.0) + if(LIBUSB_1_FOUND) + include_directories("${LIBUSB_1_INCLUDE_DIR}") + endif(LIBUSB_1_FOUND) +endif(WITH_LIBUSB) # OpenNI -find_package(OpenNI) -if (OPENNI_FOUND) - set(HAVE_OPENNI ON) - include_directories(SYSTEM ${OPENNI_INCLUDE_DIRS}) -endif() +option(WITH_OPENNI "OpenNI driver support" TRUE) +if(WITH_OPENNI) + find_package(OpenNI) + if (OPENNI_FOUND) + set(HAVE_OPENNI ON) + include_directories(SYSTEM ${OPENNI_INCLUDE_DIRS}) + endif(OPENNI_FOUND) +endif(WITH_OPENNI) + +# OpenNI 2 +option(WITH_OPENNI2 "OpenNI 2 driver support" TRUE) +if(WITH_OPENNI2) + find_package(OpenNI2) + if (OPENNI2_FOUND) + set(HAVE_OPENNI2 ON) + include_directories(SYSTEM ${OPENNI2_INCLUDE_DIRS}) + endif(OPENNI2_FOUND) +endif(WITH_OPENNI2) # Fotonic (FZ_API) -find_package(FZAPI) -if (FZAPI_FOUND) - set(HAVE_FZAPI ON) - include_directories(SYSTEM ${FZAPI_INCLUDE_DIR}) -endif() +option(WITH_FZAPI "Build Fotonic Camera support" TRUE) +if(WITH_FZAPI) + find_package(FZAPI) + if (FZAPI_FOUND) + set(HAVE_FZAPI ON) + include_directories(SYSTEM "${FZAPI_INCLUDE_DIR}") + endif(FZAPI_FOUND) +endif(WITH_FZAPI) # Intel Perceptional Computing Interface (PXCAPI) -find_package(PXCAPI) -if (PXCAPI_FOUND) - set(HAVE_PXCAPI ON) - include_directories(SYSTEM ${PXCAPI_INCLUDE_DIRS}) +option(WITH_PXCAPI "Build PXC Device support" TRUE) +if(WITH_PXCAPI) + find_package(PXCAPI) + if (PXCAPI_FOUND) + set(HAVE_PXCAPI ON) + include_directories(SYSTEM ${PXCAPI_INCLUDE_DIRS}) + endif(PXCAPI_FOUND) +endif(WITH_PXCAPI) + +# metslib +if (PKG_CONFIG_FOUND) + pkg_check_modules(METSLIB metslib) + if (METSLIB_FOUND) + set (HAVE_METSLIB ON) + include_directories(${METSLIB_INCLUDE_DIRS}) + else() + include_directories("${PCL_SOURCE_DIR}/recognition/include/pcl/recognition/3rdparty/") + endif() +else() + include_directories(${PCL_SOURCE_DIR}/recognition/include/pcl/recognition/3rdparty/) endif() # LibPNG -find_package(PNG) -if (PNG_FOUND) - set (HAVE_PNG ON) - include_directories(${PNG_INCLUDE_DIR}) -endif(PNG_FOUND) +option(WITH_PNG "PNG file support" TRUE) +if(WITH_PNG) + find_package(PNG) + if (PNG_FOUND) + set (HAVE_PNG ON) + include_directories("${PNG_INCLUDE_DIR}") + endif(PNG_FOUND) +endif(WITH_PNG) # Qhull -if(NOT PCL_SHARED_LIBS OR WIN32) - set(QHULL_USE_STATIC ON) -endif(NOT PCL_SHARED_LIBS OR WIN32) -find_package(Qhull) - -# Find Qt5 -include(cmake/pcl_find_qt5.cmake) - -# Find QT4 -if(NOT QT5_FOUND) - find_package(Qt4) - if (QT4_FOUND) - include(${QT_USE_FILE}) - endif (QT4_FOUND) -endif() +option(WITH_QHULL "Include convex-hull operations" TRUE) +if(WITH_QHULL) + if(NOT PCL_SHARED_LIBS OR WIN32) + set(QHULL_USE_STATIC ON) + endif(NOT PCL_SHARED_LIBS OR WIN32) + find_package(Qhull) +endif(WITH_QHULL) + +option(WITH_QT "Build QT Front-End" TRUE) +if(WITH_QT) + # Find Qt4 + find_package(Qt4) + if (QT4_FOUND) + include("${QT_USE_FILE}") + endif (QT4_FOUND) + + # Find QT5 + if(NOT QT4_FOUND) + include(cmake/pcl_find_qt5.cmake) + endif(NOT QT4_FOUND) +endif(WITH_QT) # Find VTK -find_package(VTK) -if(VTK_FOUND) - if (PCL_SHARED_LIBS OR - (NOT (PCL_SHARED_LIBS) AND NOT (VTK_BUILD_SHARED_LIBS))) - set(VTK_FOUND TRUE) - find_package (QVTK) - message(STATUS "VTK found (include: ${VTK_INCLUDE_DIRS}, lib: ${VTK_LIBRARY_DIRS})") - link_directories(${VTK_LIBRARY_DIRS}) - set(HAVE_VTK ON) - else () - set(VTK_FOUND OFF) - set(HAVE_VTK OFF) - message ("Warning: You are to build PCL in STATIC but VTK is SHARED!") - message ("Warning: VTK disabled!") - endif () -endif(VTK_FOUND) -# Find MPI -if (WITH_MPI) # this script searches for MPI 10 sec under windows, annoying especially if you do this often - find_package(MPI) - if(MPI_CXX_FOUND) - include_directories(SYSTEM ${MPI_INCLUDE_PATH}) - endif(MPI_CXX_FOUND) -endif() -#Find Doxygen and html help compiler if any -find_package(Doxygen) -if(DOXYGEN_FOUND) - find_package(HTMLHelp) -endif(DOXYGEN_FOUND) +option(WITH_VTK "Build VTK-Visualizations" TRUE) +if(WITH_VTK AND NOT ANDROID) + find_package(VTK) + if(VTK_FOUND) + message(STATUS "VTK_MAJOR_VERSION ${VTK_MAJOR_VERSION}") + if (PCL_SHARED_LIBS OR + (NOT (PCL_SHARED_LIBS) AND NOT (VTK_BUILD_SHARED_LIBS))) + set(VTK_FOUND TRUE) + find_package (QVTK) + if (${VTK_MAJOR_VERSION} VERSION_LESS "6.0") + message(STATUS "VTK found (include: ${VTK_INCLUDE_DIRS}, lib: ${VTK_LIBRARY_DIRS})") + link_directories(${VTK_LIBRARY_DIRS}) + else(${VTK_MAJOR_VERSION} VERSION_LESS "6.0") + include (${VTK_USE_FILE}) + message(STATUS "VTK found (include: ${VTK_INCLUDE_DIRS}, lib: ${VTK_LIBRARIES}") + endif (${VTK_MAJOR_VERSION} VERSION_LESS "6.0") + if (APPLE) + option (VTK_USE_COCOA "Use Cocoa for VTK render windows" ON) + MARK_AS_ADVANCED (VTK_USE_COCOA) + endif (APPLE) + set(HAVE_VTK ON) + else () + set(VTK_FOUND OFF) + set(HAVE_VTK OFF) + message ("Warning: You are to build PCL in STATIC but VTK is SHARED!") + message ("Warning: VTK disabled!") + endif () + endif(VTK_FOUND) +else(WITH_VTK AND NOT ANDROID) + set(VTK_FOUND OFF) + set(HAVE_VTK OFF) +endif(WITH_VTK AND NOT ANDROID) + + #Find PCAP -find_package(Pcap) +option(WITH_PCAP "pcap file capabilities in Velodyne HDL driver" TRUE) +if(WITH_PCAP) + find_package(Pcap) +endif(WITH_PCAP) + +# OpenGL and GLUT +include("${PCL_SOURCE_DIR}/cmake/pcl_find_gl.cmake") ### ---[ Create the config.h file set(pcl_config_h_in "${CMAKE_CURRENT_SOURCE_DIR}/pcl_config.h.in") set(pcl_config_h "${CMAKE_CURRENT_BINARY_DIR}/include/pcl/pcl_config.h") -configure_file(${pcl_config_h_in} ${pcl_config_h}) -PCL_ADD_INCLUDES(common "" ${pcl_config_h}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) +configure_file("${pcl_config_h_in}" "${pcl_config_h}") +PCL_ADD_INCLUDES(common "" "${pcl_config_h}") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/include") ### ---[ Set up for tests enable_testing() ### ---[ Set up for examples -#include(${PCL_SOURCE_DIR}/cmake/pcl_examples.cmake) +#include("${PCL_SOURCE_DIR}/cmake/pcl_examples.cmake") ### ---[ Add the libraries subdirectories -include(${PCL_SOURCE_DIR}/cmake/pcl_targets.cmake) +include("${PCL_SOURCE_DIR}/cmake/pcl_targets.cmake") -collect_subproject_directory_names(${PCL_SOURCE_DIR} "CMakeLists.txt" PCL_MODULES_NAMES PCL_MODULES_DIRS doc) +collect_subproject_directory_names("${PCL_SOURCE_DIR}" "CMakeLists.txt" PCL_MODULES_NAMES PCL_MODULES_DIRS doc) set(PCL_MODULES_NAMES_UNSORTED ${PCL_MODULES_NAMES}) topological_sort(PCL_MODULES_NAMES PCL_ _DEPENDS) sort_relative(PCL_MODULES_NAMES_UNSORTED PCL_MODULES_NAMES PCL_MODULES_DIRS) foreach(subdir ${PCL_MODULES_DIRS}) - add_subdirectory(${PCL_SOURCE_DIR}/${subdir}) + add_subdirectory("${PCL_SOURCE_DIR}/${subdir}") endforeach(subdir) ### ---[ Documentation add_subdirectory(doc) ### ---[ Configure PCLConfig.cmake -include(${PCL_SOURCE_DIR}/cmake/pcl_pclconfig.cmake) +include("${PCL_SOURCE_DIR}/cmake/pcl_pclconfig.cmake") ### ---[ Package creation -include(${PCL_SOURCE_DIR}/cmake/pcl_all_in_one_installer.cmake) -include(${PCL_SOURCE_DIR}/cmake/pcl_cpack.cmake) +include("${PCL_SOURCE_DIR}/cmake/pcl_all_in_one_installer.cmake") +include("${PCL_SOURCE_DIR}/cmake/pcl_cpack.cmake") if(CPACK_GENERATOR) message(STATUS "Found CPack generators: ${CPACK_GENERATOR}") @@ -364,7 +429,7 @@ if(CPACK_GENERATOR) include(CPack) endif(CPACK_GENERATOR) ### ---[ Make a pretty picture of the dependency graph -include(${PCL_SOURCE_DIR}/cmake/dep_graph.cmake) +include("${PCL_SOURCE_DIR}/cmake/dep_graph.cmake") MAKE_DEP_GRAPH() ### ---[ Finish up diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..46cba519 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,147 @@ +# Contributing to PCL + +Please take a moment to review this document in order to make the contribution +process easy and effective for everyone involved. + +Following these guidelines helps to communicate that you respect the time of +the developers managing and developing this open source project. In return, +they should reciprocate that respect in addressing your issue or assessing +patches and features. + + +## Using the issue tracker + +The [issue tracker](https://github.com/PointCloudLibrary/pcl/issues) is +the preferred channel for submitting [pull requests](#pull-requests) and +[bug reports](#bugs), but please respect the following +restrictions: + +* Please **do not** use the issue tracker for personal support requests (use + [mailing list](http://www.pcl-users.org/)). + +* Please **do not** derail or troll issues. Keep the discussion on topic and + respect the opinions of others. + + + +## Pull requests + +Good pull requests - patches, improvements, new features - are a fantastic +help. They should remain focused in scope and avoid containing unrelated +commits. + +**Please ask first** before embarking on any significant pull request (e.g. +implementing features, refactoring code), otherwise you risk spending a lot of +time working on something that the project's developers might not want to merge +into the project. Please read the [tutorial on writing a new PCL class](http://pointclouds.org/documentation/tutorials/writing_new_classes.php#writing-new-classes) if you want to contribute a +brand new feature. + +If you are new to Git, GitHub, or contributing to an open-source project, you +may want to consult the [step-by-step guide on preparing and submitting a pull request](https://github.com/PointCloudLibrary/pcl/wiki/A-step-by-step-guide-on-preparing-and-submitting-a-pull-request). + + + +### Checklist + +Please use the following checklist to make sure that your contribution is well +prepared for merging into PCL: + +1. Source code adheres to the coding conventions described in [PCL Style Guide](http://pointclouds.org/documentation/advanced/pcl_style_guide.php). + But if you modify existing code, do not change/fix style in the lines that + are not related to your contribution. + +2. Commit history is tidy (no merge commits, commits are [squashed](http://davidwalsh.name/squash-commits-git) + into logical units). + +3. Each contributed file has a [license](#license) text on top. + + + +## Bug reports + +A bug is a _demonstrable problem_ that is caused by the code in the repository. +Good bug reports are extremely helpful - thank you! + +Guidelines for bug reports: + +1. **Check if the issue has been reported** — use GitHub issue search and + mailing list archive search. + +2. **Check if the issue has been fixed** — try to reproduce it using the + latest `master` branch in the repository. + +3. **Isolate the problem** — ideally create a reduced test + case. + +A good bug report shouldn't leave others needing to chase you up for more +information. Please try to be as detailed as possible in your report. What is +your environment? What steps will reproduce the issue? What would you expect to +be the outcome? All these details will help people to fix any potential bugs. + +Example: + +> Short and descriptive example bug report title +> +> A summary of the issue and the OS environment in which it occurs. If +> suitable, include the steps required to reproduce the bug. +> +> 1. This is the first step +> 2. This is the second step +> 3. Further steps, etc. +> +> Any other information you want to share that is relevant to the issue being +> reported. This might include the lines of code that you have identified as +> causing the bug, and potential solutions (and your opinions on their +> merits). + + + +## License + +PCL is 100% [BSD licensed](LICENSE.txt), and by submitting a patch, you agree to +allow Open Perception, Inc. to license your work under the terms of the BSD +License. The corpus of the license should be inserted as a C++ comment on top +of each `.h` and `.cpp` file: + +```cpp +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2014-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +``` + +Please note that if the academic institution or company you are affiliated with +does not allow to give up the rights, you may insert an additional copyright +line. diff --git a/PCLConfig.cmake.in b/PCLConfig.cmake.in index 5076f626..65ea6881 100644 --- a/PCLConfig.cmake.in +++ b/PCLConfig.cmake.in @@ -80,8 +80,9 @@ macro(find_boost) endif(PCL_ALL_IN_ONE_INSTALLER) # use static Boost in Windows if(WIN32) - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_STATIC ON) + set(Boost_USE_STATIC_LIBS @Boost_USE_STATIC_LIBS@) + set(Boost_USE_STATIC @Boost_USE_STATIC@) + set(Boost_USE_MULTITHREAD @Boost_USE_MULTITHREAD@) endif(WIN32) if(${CMAKE_VERSION} VERSION_LESS 2.8.5) SET(Boost_ADDITIONAL_VERSIONS "1.43" "1.43.0" "1.44" "1.44.0" "1.45" "1.45.0" "1.46.1" "1.46.0" "1.46" "1.47" "1.47.0") @@ -139,14 +140,13 @@ macro(find_qhull) # Most likely we are on windows so prefer static libraries over shared ones (Mourad's recommend) find_library(QHULL_LIBRARY - NAMES qhullstatic qhull qhull${QHULL_MAJOR_VERSION} + NAMES "@QHULL_LIBRARY_NAME@" HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" PATHS "$ENV{PROGRAMFILES}/qhull" "$ENV{PROGRAMW6432}/qhull" PATH_SUFFIXES project build bin lib) find_library(QHULL_LIBRARY_DEBUG - NAMES qhullstatic_d qhull_d qhull${QHULL_MAJOR_VERSION}_d qhull_d${QHULL_MAJOR_VERSION} - qhull qhull${QHULL_MAJOR_VERSION} + NAMES "@QHULL_LIBRARY_DEBUG_NAME@" HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" PATHS "$ENV{PROGRAMFILES}/qhull" "$ENV{PROGRAMW6432}/qhull" PATH_SUFFIXES project build bin lib) @@ -210,6 +210,43 @@ macro(find_openni) endif(OPENNI_FOUND) endmacro(find_openni) +#remove this as soon as openni2-dev is shipped with FindOpenni2.cmake +macro(find_openni2) + if(NOT OPENNI2_ROOT AND ("ON" STREQUAL "ON")) + get_filename_component(OPENNI2_LIBRARY_HINT "OPENNI_LIBRARY-NOTFOUND" PATH) + endif(NOT OPENNI2_ROOT AND ("ON" STREQUAL "ON")) + + set(OPENNI2_SUFFIX) + if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + set(OPENNI2_SUFFIX 64) + endif(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_OPENNI2 openni2-dev) + endif(PKG_CONFIG_FOUND) + + find_path(OPENNI2_INCLUDE_DIRS OpenNI.h + HINTS /usr/include/openni2 /usr/include/ni2 + PATHS "$ENV{OPENNI2_INCLUDE${OPENNI2_SUFFIX}}" + PATH_SUFFIXES openni openni2 include Include) + + find_library(OPENNI2_LIBRARY + NAMES OpenNI2 # No suffix needed on Win64 + HINTS /usr/lib + PATHS "$ENV{OPENNI2_LIB${OPENNI2_SUFFIX}}" + PATH_SUFFIXES lib Lib Lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(OpenNI2 DEFAULT_MSG OPENNI2_LIBRARY OPENNI2_INCLUDE_DIRS) + + if(OPENNI2_FOUND) + get_filename_component(OPENNI_LIBRARY_PATH ${OPENNI2_LIBRARY} PATH) + set(OPENNI2_LIBRARY_DIRS ${OPENNI2_LIBRARY_PATH}) + set(OPENNI2_LIBRARIES "${OPENNI2_LIBRARY}") + set(OPENNI2_REDIST_DIR $ENV{OPENNI2_REDIST${OPENNI2_SUFFIX}}) + endif(OPENNI2_FOUND) +endmacro(find_openni2) + #remove this as soon as flann is shipped with FindFlann.cmake macro(find_flann) if(PCL_ALL_IN_ONE_INSTALLER) @@ -260,15 +297,17 @@ macro(find_flann) endmacro(find_flann) macro(find_VTK) - if(PCL_ALL_IN_ONE_INSTALLER) + if(PCL_ALL_IN_ONE_INSTALLER AND NOT ANDROID) set(VTK_DIR "${PCL_ROOT}/3rdParty/VTK/lib/vtk-5.8") - elseif(NOT VTK_DIR) + elseif(NOT VTK_DIR AND NOT ANDROID) set(VTK_DIR "@VTK_DIR@") - endif(PCL_ALL_IN_ONE_INSTALLER) - find_package(VTK ${QUIET_}) - if (VTK_FOUND AND NOT ANDROID) - set(VTK_LIBRARIES vtkCommon vtkRendering vtkHybrid vtkCharts) - endif(VTK_FOUND AND NOT ANDROID) + endif(PCL_ALL_IN_ONE_INSTALLER AND NOT ANDROID) + if(NOT ANDROID) + find_package(VTK ${QUIET_}) + if (VTK_FOUND) + set(VTK_LIBRARIES "@VTK_LIBRARIES@") + endif(VTK_FOUND) + endif() endmacro(find_VTK) macro(find_libusb) @@ -401,6 +440,8 @@ macro(find_external_library _component _lib _is_optional) find_qhull() elseif("${_lib}" STREQUAL "openni") find_openni() + elseif("${_lib}" STREQUAL "openni2") + find_openni2() elseif("${_lib}" STREQUAL "vtk") find_VTK() elseif("${_lib}" STREQUAL "libusb-1.0") @@ -423,9 +464,9 @@ macro(find_external_library _component _lib _is_optional) if(${LIB}_LIBRARIES) list(APPEND PCL_${COMPONENT}_LIBRARIES "${${LIB}_LIBRARIES}") endif(${LIB}_LIBRARIES) - if(${LIB}_DEFINITIONS) + if(${LIB}_DEFINITIONS AND NOT ${LIB} STREQUAL "VTK") list(APPEND PCL_${COMPONENT}_DEFINITIONS ${${LIB}_DEFINITIONS}) - endif(${LIB}_DEFINITIONS) + endif(${LIB}_DEFINITIONS AND NOT ${LIB} STREQUAL "VTK") else(${LIB}_FOUND) if("${_is_optional}" STREQUAL "OPTIONAL") add_definitions("-DDISABLE_${LIB}") @@ -503,6 +544,14 @@ if(EXISTS "${PCL_ROOT}/include/pcl-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}/pcl if(EXISTS "${PCL_ROOT}/3rdParty") set(PCL_ALL_IN_ONE_INSTALLER ON) endif(EXISTS "${PCL_ROOT}/3rdParty") +elseif(EXISTS "${PCL_ROOT}/include/pcl/pcl_config.h") + # Found a non-standard (likely ANDROID) PCL installation + # pcl_message("Found a PCL installation") + set(PCL_INCLUDE_DIRS "${PCL_ROOT}/include") + set(PCL_LIBRARY_DIRS "${PCL_ROOT}/lib") + if(EXISTS "${PCL_ROOT}/3rdParty") + set(PCL_ALL_IN_ONE_INSTALLER ON) + endif(EXISTS "${PCL_ROOT}/3rdParty") elseif(EXISTS "${PCL_DIR}/include/pcl/pcl_config.h") # Found PCLConfig.cmake in a build tree of PCL # pcl_message("PCL found into a build tree.") @@ -528,7 +577,7 @@ list(LENGTH pcl_all_components PCL_NB_COMPONENTS) @PCLCONFIG_OPTIONAL_DEPENDENCIES@ -set(pcl_header_only_components geometry modeler in_hand_scanner) +set(pcl_header_only_components geometry modeler in_hand_scanner point_cloud_editor cloud_composer optronic_viewer) include(FindPackageHandleStandardArgs) @@ -603,6 +652,12 @@ foreach(component ${PCL_TO_FIND_COMPONENTS}) PATH) endif(PCL_${COMPONENT}_LIBRARY_DEBUG) + # Restrict this to Windows users + if(NOT PCL_${COMPONENT}_LIBRARY AND WIN32) + # might be debug only + set(PCL_${COMPONENT}_LIBRARY ${PCL_${COMPONENT}_LIBRARY_DEBUG}) + endif(NOT PCL_${COMPONENT}_LIBRARY AND WIN32) + find_package_handle_standard_args(PCL_${COMPONENT} DEFAULT_MSG PCL_${COMPONENT}_LIBRARY PCL_${COMPONENT}_INCLUDE_DIR) else(_is_header_only EQUAL -1) @@ -649,15 +704,6 @@ if(NOT "${PCL_LIBRARY_DIRS}" STREQUAL "") list(REMOVE_DUPLICATES PCL_LIBRARY_DIRS) endif(NOT "${PCL_LIBRARY_DIRS}" STREQUAL "") -# We need to export march=native for tutorials or user code -if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") -list (APPEND PCL_DEFINITIONS "@SSE_FLAGS@") -endif() - -if(NOT MSVC) -list (APPEND PCL_DEFINITIONS "-Wno-invalid-offsetof") -endif(NOT MSVC) - if(NOT "${PCL_DEFINITIONS}" STREQUAL "") list(REMOVE_DUPLICATES PCL_DEFINITIONS) endif(NOT "${PCL_DEFINITIONS}" STREQUAL "") @@ -665,7 +711,7 @@ endif(NOT "${PCL_DEFINITIONS}" STREQUAL "") pcl_remove_duplicate_libraries(PCL_LIBRARIES PCL_DEDUP_LIBRARIES) set(PCL_LIBRARIES ${PCL_DEDUP_LIBRARIES}) # Add 3rd party libraries, as user code might include our .HPP implementations -list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${QHULL_LIBRARIES} ${OPENNI_LIBRARIES} ${FLANN_LIBRARIES} ${VTK_LIBRARIES}) +list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${QHULL_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${FLANN_LIBRARIES} ${VTK_LIBRARIES}) find_package_handle_standard_args(PCL DEFAULT_MSG PCL_LIBRARIES PCL_INCLUDE_DIRS) mark_as_advanced(PCL_LIBRARIES PCL_INCLUDE_DIRS PCL_LIBRARY_DIRS) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index cf80bbc9..93b11e97 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -9,7 +9,7 @@ if(NOT VTK_FOUND) else(NOT VTK_FOUND) set(DEFAULT TRUE) set(REASON) - include (${VTK_USE_FILE}) + include("${VTK_USE_FILE}") endif(NOT VTK_FOUND) # OpenNI found? @@ -22,140 +22,143 @@ else(NOT OPENNI_FOUND) endif(NOT OPENNI_FOUND) set(DEFAULT FALSE) -PCL_SUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSYS_DESC} ${DEFAULT} ${REASON}) -PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS openni vtk) +PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") +PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni vtk) if(build) - include_directories (${CMAKE_CURRENT_BINARY_DIR}) - include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include) + include_directories("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include") - PCL_ADD_EXECUTABLE(pcl_test_search_speed ${SUBSYS_NAME} src/test_search.cpp) + PCL_ADD_EXECUTABLE(pcl_test_search_speed "${SUBSYS_NAME}" src/test_search.cpp) target_link_libraries(pcl_test_search_speed pcl_common pcl_io pcl_search pcl_kdtree pcl_visualization) - PCL_ADD_EXECUTABLE(pcl_nn_classification_example ${SUBSYS_NAME} src/nn_classification_example.cpp) + PCL_ADD_EXECUTABLE(pcl_nn_classification_example "${SUBSYS_NAME}" src/nn_classification_example.cpp) target_link_libraries(pcl_nn_classification_example pcl_common pcl_io pcl_features pcl_kdtree) - PCL_ADD_EXECUTABLE(pcl_pyramid_surface_matching ${SUBSYS_NAME} src/pyramid_surface_matching.cpp) + PCL_ADD_EXECUTABLE(pcl_pyramid_surface_matching "${SUBSYS_NAME}" src/pyramid_surface_matching.cpp) target_link_libraries(pcl_pyramid_surface_matching pcl_common pcl_io pcl_features pcl_registration pcl_filters) - PCL_ADD_EXECUTABLE(pcl_statistical_multiscale_interest_region_extraction_example ${SUBSYS_NAME} src/statistical_multiscale_interest_region_extraction_example.cpp) + PCL_ADD_EXECUTABLE(pcl_statistical_multiscale_interest_region_extraction_example "${SUBSYS_NAME}" src/statistical_multiscale_interest_region_extraction_example.cpp) target_link_libraries(pcl_statistical_multiscale_interest_region_extraction_example pcl_common pcl_io pcl_features pcl_filters) if(LIBUSB_1_FOUND) - PCL_ADD_EXECUTABLE(pcl_dinast_grabber ${SUBSYS_NAME} src/dinast_grabber_example.cpp) + PCL_ADD_EXECUTABLE(pcl_dinast_grabber "${SUBSYS_NAME}" src/dinast_grabber_example.cpp) target_link_libraries(pcl_dinast_grabber pcl_common pcl_visualization pcl_io) endif(LIBUSB_1_FOUND) if (VTK_FOUND) - PCL_ADD_EXECUTABLE(pcl_ppf_object_recognition ${SUBSYS_NAME} src/ppf_object_recognition.cpp) + PCL_ADD_EXECUTABLE(pcl_ppf_object_recognition "${SUBSYS_NAME}" src/ppf_object_recognition.cpp) target_link_libraries(pcl_ppf_object_recognition pcl_common pcl_io pcl_filters pcl_features pcl_registration pcl_visualization pcl_sample_consensus pcl_segmentation) - PCL_ADD_EXECUTABLE(pcl_multiscale_feature_persistence_example ${SUBSYS_NAME} src/multiscale_feature_persistence_example.cpp) + PCL_ADD_EXECUTABLE(pcl_multiscale_feature_persistence_example "${SUBSYS_NAME}" src/multiscale_feature_persistence_example.cpp) target_link_libraries(pcl_multiscale_feature_persistence_example pcl_common pcl_io pcl_filters pcl_features pcl_visualization) - PCL_ADD_EXECUTABLE(pcl_surfel_smoothing_test ${SUBSYS_NAME} src/surfel_smoothing_test.cpp) + PCL_ADD_EXECUTABLE(pcl_surfel_smoothing_test "${SUBSYS_NAME}" src/surfel_smoothing_test.cpp) target_link_libraries(pcl_surfel_smoothing_test pcl_common pcl_io pcl_surface pcl_filters pcl_features pcl_visualization) - PCL_ADD_EXECUTABLE(pcl_feature_matching ${SUBSYS_NAME} src/feature_matching.cpp) + PCL_ADD_EXECUTABLE(pcl_feature_matching "${SUBSYS_NAME}" src/feature_matching.cpp) target_link_libraries(pcl_feature_matching pcl_common pcl_io pcl_registration pcl_keypoints pcl_sample_consensus pcl_visualization pcl_search pcl_features pcl_kdtree pcl_surface pcl_segmentation) - PCL_ADD_EXECUTABLE(pcl_convolve ${SUBSYS_NAME} src/convolve.cpp) + PCL_ADD_EXECUTABLE(pcl_convolve "${SUBSYS_NAME}" src/convolve.cpp) target_link_libraries(pcl_convolve pcl_common pcl_io pcl_visualization) - PCL_ADD_EXECUTABLE(pcl_pcd_organized_multi_plane_segmentation ${SUBSYS_NAME} src/pcd_organized_multi_plane_segmentation.cpp) + PCL_ADD_EXECUTABLE(pcl_pcd_organized_multi_plane_segmentation "${SUBSYS_NAME}" src/pcd_organized_multi_plane_segmentation.cpp) target_link_libraries(pcl_pcd_organized_multi_plane_segmentation pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_features) if (QHULL_FOUND) - PCL_ADD_EXECUTABLE(pcl_pcd_select_object_plane ${SUBSYS_NAME} src/pcd_select_object_plane.cpp) + PCL_ADD_EXECUTABLE(pcl_pcd_select_object_plane "${SUBSYS_NAME}" src/pcd_select_object_plane.cpp) target_link_libraries(pcl_pcd_select_object_plane pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_features pcl_surface) endif() -# PCL_ADD_EXECUTABLE(pcl_convolve ${SUBSYS_NAME} src/convolve.cpp) +# PCL_ADD_EXECUTABLE(pcl_convolve "${SUBSYS_NAME}" src/convolve.cpp) # target_link_libraries(pcl_convolve pcl_common pcl_io pcl_visualization) + if (QT4_FOUND AND VTK_USE_QVTK) + + # Manual registration demo + QT4_WRAP_UI(manual_registration_ui src/manual_registration/manual_registration.ui) + QT4_WRAP_CPP(manual_registration_moc include/pcl/apps/manual_registration.h OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_manual_registration "${SUBSYS_NAME}" ${manual_registration_ui} ${manual_registration_moc} src/manual_registration/manual_registration.cpp) + target_link_libraries(pcl_manual_registration pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QVTK_LIBRARY} ${QT_LIBRARIES}) + + QT4_WRAP_UI(pcd_video_player_ui src/pcd_video_player/pcd_video_player.ui) + QT4_WRAP_CPP(pcd_video_player_moc include/pcl/apps/pcd_video_player.h OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_pcd_video_player "${SUBSYS_NAME}" ${pcd_video_player_ui} ${pcd_video_player_moc} src/pcd_video_player/pcd_video_player.cpp) + target_link_libraries(pcl_pcd_video_player pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QVTK_LIBRARY} ${QT_LIBRARIES}) + + endif (QT4_FOUND AND VTK_USE_QVTK) + if (OPENNI_FOUND AND BUILD_OPENNI) -# PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_grab_frame ${SUBSYS_NAME} src/openni_grab_frame.cpp) +# PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_grab_frame "${SUBSYS_NAME}" src/openni_grab_frame.cpp) # target_link_libraries(pcl_openni_grab_frame pcl_common pcl_io pcl_visualization) -# PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_grab_images ${SUBSYS_NAME} src/openni_grab_images.cpp) +# PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_grab_images "${SUBSYS_NAME}" src/openni_grab_images.cpp) # target_link_libraries(pcl_openni_grab_images pcl_common pcl_io pcl_visualization) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_fast_mesh ${SUBSYS_NAME} src/openni_fast_mesh.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_fast_mesh "${SUBSYS_NAME}" src/openni_fast_mesh.cpp) target_link_libraries(pcl_openni_fast_mesh pcl_common pcl_io pcl_visualization pcl_surface) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_voxel_grid ${SUBSYS_NAME} src/openni_voxel_grid.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_voxel_grid "${SUBSYS_NAME}" src/openni_voxel_grid.cpp) target_link_libraries(pcl_openni_voxel_grid pcl_common pcl_io pcl_filters pcl_visualization) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_octree_compression ${SUBSYS_NAME} src/openni_octree_compression.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_octree_compression "${SUBSYS_NAME}" src/openni_octree_compression.cpp) target_link_libraries(pcl_openni_octree_compression pcl_common pcl_io pcl_filters pcl_visualization pcl_octree) if(HAVE_PNG) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_organized_compression ${SUBSYS_NAME} src/openni_organized_compression.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_organized_compression "${SUBSYS_NAME}" src/openni_organized_compression.cpp) target_link_libraries(pcl_openni_organized_compression pcl_common pcl_io pcl_filters pcl_visualization pcl_octree) endif(HAVE_PNG) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_shift_to_depth_conversion ${SUBSYS_NAME} src/openni_shift_to_depth_conversion.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_shift_to_depth_conversion "${SUBSYS_NAME}" src/openni_shift_to_depth_conversion.cpp) target_link_libraries(pcl_openni_shift_to_depth_conversion pcl_common pcl_visualization) - PCL_ADD_EXECUTABLE(pcl_openni_mobile_server ${SUBSYS_NAME} src/openni_mobile_server.cpp) + PCL_ADD_EXECUTABLE(pcl_openni_mobile_server "${SUBSYS_NAME}" src/openni_mobile_server.cpp) target_link_libraries(pcl_openni_mobile_server pcl_common pcl_io pcl_filters pcl_visualization) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_planar_segmentation ${SUBSYS_NAME} src/openni_planar_segmentation.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_planar_segmentation "${SUBSYS_NAME}" src/openni_planar_segmentation.cpp) target_link_libraries(pcl_openni_planar_segmentation pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_organized_multi_plane_segmentation ${SUBSYS_NAME} src/openni_organized_multi_plane_segmentation.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_organized_multi_plane_segmentation "${SUBSYS_NAME}" src/openni_organized_multi_plane_segmentation.cpp) target_link_libraries(pcl_openni_organized_multi_plane_segmentation pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_features) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_ii_normal_estimation ${SUBSYS_NAME} src/openni_ii_normal_estimation.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_ii_normal_estimation "${SUBSYS_NAME}" src/openni_ii_normal_estimation.cpp) target_link_libraries(pcl_openni_ii_normal_estimation pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_surface) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_feature_persistence ${SUBSYS_NAME} src/openni_feature_persistence.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_feature_persistence "${SUBSYS_NAME}" src/openni_feature_persistence.cpp) target_link_libraries(pcl_openni_feature_persistence pcl_common pcl_io pcl_filters pcl_visualization pcl_features) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_mls_smoothing ${SUBSYS_NAME} src/openni_mls_smoothing.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_mls_smoothing "${SUBSYS_NAME}" src/openni_mls_smoothing.cpp) target_link_libraries(pcl_openni_mls_smoothing pcl_common pcl_io pcl_surface pcl_visualization) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_change_viewer ${SUBSYS_NAME} src/openni_change_viewer.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_change_viewer "${SUBSYS_NAME}" src/openni_change_viewer.cpp) target_link_libraries(pcl_openni_change_viewer pcl_common pcl_io pcl_kdtree pcl_octree pcl_visualization pcl_filters) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_uniform_sampling ${SUBSYS_NAME} src/openni_uniform_sampling.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_uniform_sampling "${SUBSYS_NAME}" src/openni_uniform_sampling.cpp) target_link_libraries(pcl_openni_uniform_sampling pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_surface pcl_keypoints) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_boundary_estimation ${SUBSYS_NAME} src/openni_boundary_estimation.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_boundary_estimation "${SUBSYS_NAME}" src/openni_boundary_estimation.cpp) target_link_libraries(pcl_openni_boundary_estimation pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_surface) if (QT4_FOUND AND VTK_USE_QVTK) # OpenNI Passthrough application demo QT4_WRAP_UI(openni_passthrough_ui src/openni_passthrough.ui) QT4_WRAP_CPP(openni_passthrough_moc include/pcl/apps/openni_passthrough.h OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - PCL_ADD_EXECUTABLE(pcl_openni_passthrough ${SUBSYS_NAME} ${openni_passthrough_ui} ${openni_passthrough_moc} src/openni_passthrough.cpp) - target_link_libraries(pcl_openni_passthrough pcl_common pcl_io pcl_filters pcl_visualization QVTK ${QT_LIBRARIES}) + PCL_ADD_EXECUTABLE(pcl_openni_passthrough "${SUBSYS_NAME}" ${openni_passthrough_ui} ${openni_passthrough_moc} src/openni_passthrough.cpp) + target_link_libraries(pcl_openni_passthrough pcl_common pcl_io pcl_filters pcl_visualization ${QVTK_LIBRARY} ${QT_LIBRARIES}) # OpenNI Organized Connected Component application demo QT4_WRAP_UI(organized_segmentation_demo_ui src/organized_segmentation_demo.ui) QT4_WRAP_CPP(organized_segmentation_demo_moc include/pcl/apps/organized_segmentation_demo.h OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_organized_segmentation_demo ${SUBSYS_NAME} ${organized_segmentation_demo_ui} ${organized_segmentation_demo_moc} src/organized_segmentation_demo.cpp) - target_link_libraries(pcl_organized_segmentation_demo pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface QVTK ${QT_LIBRARIES}) - - # Manual registration demo - QT4_WRAP_UI(manual_registration_ui src/manual_registration/manual_registration.ui) - QT4_WRAP_CPP(manual_registration_moc include/pcl/apps/manual_registration.h OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_manual_registration ${SUBSYS_NAME} ${manual_registration_ui} ${manual_registration_moc} src/manual_registration/manual_registration.cpp) - target_link_libraries(pcl_manual_registration pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface QVTK ${QT_LIBRARIES}) - - QT4_WRAP_UI(pcd_video_player_ui src/pcd_video_player/pcd_video_player.ui) - QT4_WRAP_CPP(pcd_video_player_moc include/pcl/apps/pcd_video_player.h OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_pcd_video_player ${SUBSYS_NAME} ${pcd_video_player_ui} ${pcd_video_player_moc} src/pcd_video_player/pcd_video_player.cpp) - target_link_libraries(pcl_pcd_video_player pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface QVTK ${QT_LIBRARIES}) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_organized_segmentation_demo "${SUBSYS_NAME}" ${organized_segmentation_demo_ui} ${organized_segmentation_demo_moc} src/organized_segmentation_demo.cpp) + target_link_libraries(pcl_organized_segmentation_demo pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QVTK_LIBRARY} ${QT_LIBRARIES}) # Database processing (integration) demo # QT4_WRAP_UI(db_proc_ui src/db_proc/db_proc.ui) # QT4_WRAP_CPP(db_proc_moc include/pcl/apps/db_proc.h OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED) -# PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_db_proc ${SUBSYS_NAME} ${db_proc_ui} ${db_proc_moc} src/db_proc/db_proc.cpp) -# target_link_libraries(pcl_db_proc pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface QVTK ${QT_LIBRARIES}) +# PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_db_proc "${SUBSYS_NAME}" ${db_proc_ui} ${db_proc_moc} src/db_proc/db_proc.cpp) +# target_link_libraries(pcl_db_proc pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QVTK_LIBRARY} ${QT_LIBRARIES}) endif () @@ -165,58 +168,67 @@ if(build) set(srcs src/render_views_tesselated_sphere.cpp) if (QHULL_FOUND) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_3d_convex_hull ${SUBSYS_NAME} src/openni_3d_convex_hull.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_3d_convex_hull "${SUBSYS_NAME}" src/openni_3d_convex_hull.cpp) target_link_libraries(pcl_openni_3d_convex_hull pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_surface) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_3d_concave_hull ${SUBSYS_NAME} src/openni_3d_concave_hull.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_3d_concave_hull "${SUBSYS_NAME}" src/openni_3d_concave_hull.cpp) target_link_libraries(pcl_openni_3d_concave_hull pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_surface) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_tracking ${SUBSYS_NAME} src/openni_tracking.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_tracking "${SUBSYS_NAME}" src/openni_tracking.cpp) target_link_libraries(pcl_openni_tracking pcl_common pcl_io pcl_surface pcl_visualization pcl_filters pcl_features pcl_segmentation pcl_tracking pcl_search) - set(incs include/pcl/${SUBSYS_NAME}/dominant_plane_segmentation.h ${incs}) - set(impl_incs include/pcl/${SUBSYS_NAME}/impl/dominant_plane_segmentation.hpp) + set(incs "include/pcl/${SUBSYS_NAME}/dominant_plane_segmentation.h" ${incs}) + set(impl_incs "include/pcl/${SUBSYS_NAME}/impl/dominant_plane_segmentation.hpp") set(srcs src/dominant_plane_segmentation.cpp ${srcs}) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_planar_convex_hull ${SUBSYS_NAME} src/openni_planar_convex_hull.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_planar_convex_hull "${SUBSYS_NAME}" src/openni_planar_convex_hull.cpp) target_link_libraries(pcl_openni_planar_convex_hull pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ni_linemod "${SUBSYS_NAME}" src/ni_linemod.cpp) + target_link_libraries(pcl_ni_linemod pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_surface pcl_search) + endif() # QHULL_FOUND # Install include files - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME} ${incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME}/impl ${impl_incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}" ${incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/impl" ${impl_incs}) - set(LIB_NAME pcl_${SUBSYS_NAME}) - PCL_ADD_LIBRARY(${LIB_NAME} ${SUBSYS_NAME} ${srcs} ${impl_incs} ${incs}) - target_link_libraries(${LIB_NAME} pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search) + set(LIB_NAME "pcl_${SUBSYS_NAME}") + PCL_ADD_LIBRARY("${LIB_NAME}" "${SUBSYS_NAME}" ${srcs} ${impl_incs} ${incs}) + target_link_libraries("${LIB_NAME}" pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search) - PCL_MAKE_PKGCONFIG(${LIB_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" "" "" "" "" "") + PCL_MAKE_PKGCONFIG("${LIB_NAME}" "${SUBSYS_NAME}" "${SUBSYS_DESC}" "" "" "" "" "") - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ni_agast ${SUBSYS_NAME} src/ni_agast.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ni_agast "${SUBSYS_NAME}" src/ni_agast.cpp) target_link_libraries(pcl_ni_agast pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_keypoints pcl_surface pcl_search) - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ni_linemod ${SUBSYS_NAME} src/ni_linemod.cpp) - target_link_libraries(pcl_ni_linemod pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_features pcl_surface pcl_search) - - PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ni_susan ${SUBSYS_NAME} src/ni_susan.cpp) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ni_susan "${SUBSYS_NAME}" src/ni_susan.cpp) target_link_libraries(pcl_ni_susan pcl_common pcl_visualization pcl_features pcl_keypoints pcl_search) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ni_trajkovic ${SUBSYS_NAME} src/ni_trajkovic.cpp) + target_link_libraries(pcl_ni_trajkovic pcl_common pcl_visualization pcl_features pcl_keypoints pcl_search) + + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_openni_klt "${SUBSYS_NAME}" src/openni_klt.cpp) + target_link_libraries(pcl_openni_klt pcl_common pcl_io pcl_visualization pcl_tracking) endif() # OPENNI_FOUND + BUILD_OPENNI endif() # VTK_FOUND - add_subdirectory(modeler) - add_subdirectory(cloud_composer) - if(OPENNI_FOUND) - add_subdirectory(in_hand_scanner) - endif(OPENNI_FOUND) - add_subdirectory(point_cloud_editor) - if(FZAPI_FOUND) - add_subdirectory(optronic_viewer) - endif(FZAPI_FOUND) + # OpenGL and GLUT + if(OPENGL_FOUND AND GLUT_FOUND) + include_directories("${OPENGL_INCLUDE_DIR}") + include_directories("${GLUT_INCLUDE_DIR}") + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_grabcut_2d "${SUBSYS_NAME}" src/grabcut_2d.cpp) + target_link_libraries (pcl_grabcut_2d pcl_common pcl_io pcl_segmentation pcl_search ${GLUT_LIBRARIES} ${OPENGL_LIBRARIES}) + endif(OPENGL_FOUND AND GLUT_FOUND) + + collect_subproject_directory_names("${CMAKE_CURRENT_SOURCE_DIR}" "CMakeLists.txt" PCL_APPS_MODULES_NAMES PCL_APPS_MODULES_DIRS ${SUBSYS_NAME}) + set(PCL_APPS_MODULES_NAMES_UNSORTED ${PCL_APPS_MODULES_NAMES}) + topological_sort(PCL_APPS_MODULES_NAMES PCL_APPS_ _DEPENDS) + sort_relative(PCL_APPS_MODULES_NAMES_UNSORTED PCL_APPS_MODULES_NAMES PCL_APPS_MODULES_DIRS) + foreach(subdir ${PCL_APPS_MODULES_DIRS}) + add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/${subdir}") + endforeach(subdir) endif(build) - - diff --git a/apps/cloud_composer/CMakeLists.txt b/apps/cloud_composer/CMakeLists.txt index 009fd98a..d4449752 100644 --- a/apps/cloud_composer/CMakeLists.txt +++ b/apps/cloud_composer/CMakeLists.txt @@ -3,69 +3,69 @@ # string(REGEX REPLACE "-Wconversion(.+)" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") #endif() -set(SUBSYS_NAME cloud_composer) -set(SUBSYS_DESC "Cloud Composer - Application for Manipulating Point Clouds") -set(SUBSYS_DEPS common io visualization filters apps) +SET(SUBSUBSYS_NAME cloud_composer) +SET(SUBSUBSYS_DESC "Cloud Composer - Application for Manipulating Point Clouds") +SET(SUBSUBSYS_DEPS common io visualization filters apps) # Find VTK if(NOT VTK_FOUND) - set(DEFAULT FALSE) + set(DEFAULT AUTO_OFF) set(REASON "VTK was not found.") else(NOT VTK_FOUND) set(DEFAULT TRUE) set(REASON) - include (${VTK_USE_FILE}) + include("${VTK_USE_FILE}") endif(NOT VTK_FOUND) # QT4 Found? if(NOT QT4_FOUND) - set(DEFAULT FALSE) + set(DEFAULT AUTO_OFF) set(REASON "Qt4 was not found.") -else(NOT QT4_FOUND) +elseif(NOT ${DEFAULT} STREQUAL "AUTO_OFF") set(DEFAULT TRUE) set(REASON) endif(NOT QT4_FOUND) # QVTK? if(NOT VTK_USE_QVTK) - set(DEFAULT FALSE) + set(DEFAULT AUTO_OFF) set(REASON "Cloud composer requires QVTK") -else(NOT VTK_USE_QVTK) +elseif(NOT ${DEFAULT} STREQUAL "AUTO_OFF") set(DEFAULT TRUE) set(REASON) endif(NOT VTK_USE_QVTK) #Default to not building for now -set(DEFAULT FALSE) +if ("${DEFAULT}" STREQUAL "TRUE") + set(DEFAULT FALSE) +endif ("${DEFAULT}" STREQUAL "TRUE") -PCL_SUBSYS_OPTION(build app_${SUBSYS_NAME} ${SUBSYS_DESC} ${DEFAULT} ${REASON}) -PCL_SUBSYS_DEPEND(build app_${SUBSYS_NAME} ${SUBSYS_DEPS}) +PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" ${DEFAULT} "${REASON}") +PCL_SUBSUBSYS_DEPEND(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSUBSYS_DEPS}) -PCL_ADD_DOC(${SUBSYS_NAME}) +PCL_ADD_DOC(${SUBSUBSYS_NAME}) if(build) - include_directories (${CMAKE_CURRENT_BINARY_DIR}) - include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include) + include_directories("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include") - if (VTK_FOUND AND QT4_FOUND AND VTK_USE_QVTK) #Sources & Headers for main application - set(incs include/pcl/apps/${SUBSYS_NAME}/qt.h - include/pcl/apps/${SUBSYS_NAME}/cloud_composer.h - include/pcl/apps/${SUBSYS_NAME}/project_model.h - include/pcl/apps/${SUBSYS_NAME}/cloud_viewer.h - include/pcl/apps/${SUBSYS_NAME}/cloud_view.h - include/pcl/apps/${SUBSYS_NAME}/cloud_browser.h - include/pcl/apps/${SUBSYS_NAME}/item_inspector.h - include/pcl/apps/${SUBSYS_NAME}/tool_interface/abstract_tool.h - include/pcl/apps/${SUBSYS_NAME}/tool_interface/tool_factory.h - include/pcl/apps/${SUBSYS_NAME}/commands.h - include/pcl/apps/${SUBSYS_NAME}/work_queue.h - include/pcl/apps/${SUBSYS_NAME}/toolbox_model.h - include/pcl/apps/${SUBSYS_NAME}/properties_model.h - include/pcl/apps/${SUBSYS_NAME}/signal_multiplexer.h - include/pcl/apps/${SUBSYS_NAME}/merge_selection.h - include/pcl/apps/${SUBSYS_NAME}/transform_clouds.h) + set(incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/qt.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_composer.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/project_model.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_viewer.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_view.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_browser.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/item_inspector.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tool_interface/abstract_tool.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tool_interface/tool_factory.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/commands.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/work_queue.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/toolbox_model.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/properties_model.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/signal_multiplexer.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/merge_selection.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/transform_clouds.h") set(srcs src/main.cpp src/cloud_composer.cpp @@ -83,15 +83,15 @@ if(build) src/tool_interface/abstract_tool.cpp src/transform_clouds.cpp) - set(impl_incs include/pcl/apps/${SUBSYS_NAME}/impl/cloud_item.hpp - include/pcl/apps/${SUBSYS_NAME}/impl/merge_selection.hpp - include/pcl/apps/${SUBSYS_NAME}/impl/transform_clouds.hpp) + set(impl_incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/impl/cloud_item.hpp" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/impl/merge_selection.hpp" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/impl/transform_clouds.hpp") #Sources and headers for item types - set(item_incs include/pcl/apps/${SUBSYS_NAME}/items/cloud_composer_item.h - include/pcl/apps/${SUBSYS_NAME}/items/cloud_item.h - include/pcl/apps/${SUBSYS_NAME}/items/normals_item.h - include/pcl/apps/${SUBSYS_NAME}/items/fpfh_item.h) + set(item_incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/items/cloud_composer_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/items/cloud_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/items/normals_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/items/fpfh_item.h") set(item_srcs src/items/cloud_composer_item.cpp src/items/cloud_item.cpp @@ -99,10 +99,10 @@ if(build) src/items/fpfh_item.cpp) #Sources and headers for point selectors - set (selector_incs include/pcl/apps/${SUBSYS_NAME}/point_selectors/interactor_style_switch.h - include/pcl/apps/${SUBSYS_NAME}/point_selectors/rectangular_frustum_selector.h - include/pcl/apps/${SUBSYS_NAME}/point_selectors/selected_trackball_interactor_style.h - include/pcl/apps/${SUBSYS_NAME}/point_selectors/click_trackball_interactor_style.h) + set (selector_incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/point_selectors/interactor_style_switch.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/point_selectors/rectangular_frustum_selector.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/point_selectors/selected_trackball_interactor_style.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/point_selectors/click_trackball_interactor_style.h") set (selector_srcs src/point_selectors/interactor_style_switch.cpp src/point_selectors/selection_event.cpp @@ -118,80 +118,81 @@ if(build) QT4_WRAP_CPP(cloud_composer_moc ${incs} OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) QT4_ADD_RESOURCES(resource_srcs ${resources}) - set(EXE_NAME pcl_${SUBSYS_NAME}) - PCL_ADD_EXECUTABLE(${EXE_NAME} ${SUBSYS_NAME} ${cloud_composer_ui} ${cloud_composer_moc} ${srcs} ${resource_srcs} ${item_srcs} ${selector_srcs} ${impl_incs}) - target_link_libraries(${EXE_NAME} pcl_common pcl_io pcl_visualization pcl_filters QVTK ${QT_LIBRARIES}) + set(EXE_NAME "pcl_${SUBSUBSYS_NAME}") + PCL_ADD_EXECUTABLE("${EXE_NAME}" "${SUBSUBSYS_NAME}" ${cloud_composer_ui} ${cloud_composer_moc} ${srcs} ${resource_srcs} ${item_srcs} ${selector_srcs} ${impl_incs}) + target_link_libraries("${EXE_NAME}" pcl_common pcl_io pcl_visualization pcl_filters ${QVTK_LIBRARY} ${QT_LIBRARIES}) # Install include files - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME} ${incs} ${item_incs} ${selector_incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME}/impl ${impl_incs}) + PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${incs} ${item_incs} ${selector_incs}) + PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}/impl" ${impl_incs}) - PCL_MAKE_PKGCONFIG(${EXE_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" "" "" "" "" "") + PCL_MAKE_PKGCONFIG("${EXE_NAME}" "${SUBSUBSYS_NAME}" "${SUBSYS_DESC}" "" "" "" "" "") - #TOOL BUILDING SCRIPTS + #TOOL buildING SCRIPTS #Create subdirectory for plugin libs - set (CLOUD_COMPOSER_PLUGIN_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cloud_composer_plugins) - make_directory (${CLOUD_COMPOSER_PLUGIN_DIR}) + set (CLOUD_COMPOSER_PLUGIN_DIR "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cloud_composer_plugins") + make_directory("${CLOUD_COMPOSER_PLUGIN_DIR}") - set(INTERFACE_HEADERS include/pcl/apps/${SUBSYS_NAME}/tool_interface/abstract_tool.h) + set(INTERFACE_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tool_interface/abstract_tool.h") set(INTERFACE_SOURCES src/tool_interface/abstract_tool.cpp) QT4_WRAP_CPP(INTERFACE_HEADERS_MOC ${INTERFACE_HEADERS} OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - PCL_ADD_LIBRARY(pcl_cc_tool_interface ${SUBSYS_NAME} ${INTERFACE_SOURCES} ${INTERFACE_HEADERS_MOC}) + PCL_ADD_LIBRARY(pcl_cc_tool_interface "${SUBSUBSYS_NAME}" ${INTERFACE_SOURCES} ${INTERFACE_HEADERS_MOC}) target_link_libraries(pcl_cc_tool_interface pcl_common ${QT_LIBRARIES}) + + IF(APPLE) + SET_TARGET_PROPERTIES(pcl_cc_tool_interface PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + ENDIF() include(ComposerTool.cmake REQUIRED) #FPFH Tool set (FPFH_DEPS pcl_features pcl_kdtree pcl_filters) set (FPFH_SOURCES tools/fpfh_estimation.cpp) - set (FPFH_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/fpfh_estimation.h) + set (FPFH_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/fpfh_estimation.h") define_composer_tool (fpfh_estimation "${FPFH_SOURCES}" "${FPFH_HEADERS}" "${FPFH_DEPS}") #Normals Tool set (NORMALS_DEPS pcl_features pcl_kdtree) set (NORMALS_SOURCES tools/normal_estimation.cpp) - set (NORMALS_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/normal_estimation.h) + set (NORMALS_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/normal_estimation.h") define_composer_tool (normal_estimation "${NORMALS_SOURCES}" "${NORMALS_HEADERS}" "${NORMALS_DEPS}") #Euclidean Clustering Tool set (EC_DEPS pcl_segmentation pcl_kdtree) set (EC_SOURCES tools/euclidean_clustering.cpp) - set (EC_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/euclidean_clustering.h) + set (EC_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/euclidean_clustering.h") define_composer_tool (euclidean_clustering "${EC_SOURCES}" "${EC_HEADERS}" "${EC_DEPS}") #Statistical Outlier Removal Tool set (SOR_DEPS pcl_filters) set (SOR_SOURCES tools/statistical_outlier_removal.cpp) - set (SOR_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/statistical_outlier_removal.h) + set (SOR_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/statistical_outlier_removal.h") define_composer_tool (statistical_outlier_removal "${SOR_SOURCES}" "${SOR_HEADERS}" "${SOR_DEPS}") #Vox Grid Downsample Tool set (VOXDS_DEPS pcl_filters) set (VOXDS_SOURCES tools/voxel_grid_downsample.cpp) - set (VOXDS_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/voxel_grid_downsample.h) + set (VOXDS_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/voxel_grid_downsample.h") define_composer_tool (voxel_grid_downsample "${VOXDS_SOURCES}" "${VOXDS_HEADERS}" "${VOXDS_DEPS}") #Organized Segmentation set (OSEG_DEPS pcl_segmentation pcl_kdtree) - set (OSEG_SOURCES tools/organized_segmentation.cpp include/pcl/apps/${SUBSYS_NAME}/tools/impl/organized_segmentation.hpp) - set (OSEG_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/organized_segmentation.h) + set (OSEG_SOURCES tools/organized_segmentation.cpp "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/impl/organized_segmentation.hpp") + set (OSEG_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/organized_segmentation.h") define_composer_tool (organized_segmentation "${OSEG_SOURCES}" "${OSEG_HEADERS}" "${OSEG_DEPS}") #Sanitize Cloud Tool set (SAN_DEPS pcl_filters) set (SAN_SOURCES tools/sanitize_cloud.cpp) - set (SAN_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/sanitize_cloud.h) + set (SAN_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/sanitize_cloud.h") define_composer_tool (sanitize_cloud "${SAN_SOURCES}" "${SAN_HEADERS}" "${SAN_DEPS}") #Supervoxels set (VSP_DEPS pcl_octree pcl_segmentation) - set (VSP_SOURCES tools/supervoxels.cpp include/pcl/apps/${SUBSYS_NAME}/tools/impl/supervoxels.hpp) - set (VSP_HEADERS include/pcl/apps/${SUBSYS_NAME}/tools/supervoxels.h) + set (VSP_SOURCES tools/supervoxels.cpp "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/impl/supervoxels.hpp") + set (VSP_HEADERS "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/tools/supervoxels.h") define_composer_tool (supervoxels "${VSP_SOURCES}" "${VSP_HEADERS}" "${VSP_DEPS}") - - endif () #VTK_FOUND AND QT4_FOUND AND VTK_USE_QVTK - endif(build) diff --git a/apps/cloud_composer/ComposerTool.cmake b/apps/cloud_composer/ComposerTool.cmake index d55df6cb..ee37b627 100644 --- a/apps/cloud_composer/ComposerTool.cmake +++ b/apps/cloud_composer/ComposerTool.cmake @@ -21,5 +21,9 @@ function(define_composer_tool TOOL_NAME TOOL_SOURCES TOOL_HEADERS DEPS) add_dependencies(${TOOL_TARGET} pcl_cc_tool_interface ${DEPS}) target_link_libraries(${TOOL_TARGET} pcl_cc_tool_interface pcl_common pcl_io ${DEPS} ${QT_LIBRARIES}) + + IF(APPLE) + SET_TARGET_PROPERTIES(${TOOL_TARGET} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + ENDIF() endfunction(define_composer_tool TOOL_NAME TOOL_SOURCES TOOL_HEADERS DEPS) diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h index 10d4c527..0fefa8e7 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h @@ -152,3 +152,4 @@ namespace pcl Q_DECLARE_METATYPE (pcl::cloud_composer::CloudView); #endif + diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h index ca436417..4b5950e2 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h @@ -148,7 +148,7 @@ namespace pcl /** \brief Slot Called whenever the item selection_model_ changes */ void - itemSelectionChanged ( const QItemSelection & selected, const QItemSelection & deselected ); + itemSelectionChanged ( const QItemSelection &, const QItemSelection &); /** \brief Creates a new cloud from the selected items and points */ void diff --git a/apps/cloud_composer/src/cloud_view.cpp b/apps/cloud_composer/src/cloud_view.cpp index 4ad242b5..8e435451 100644 --- a/apps/cloud_composer/src/cloud_view.cpp +++ b/apps/cloud_composer/src/cloud_view.cpp @@ -195,7 +195,7 @@ pcl::cloud_composer::CloudView::selectedItemChanged (const QItemSelection & sele } void -pcl::cloud_composer::CloudView::dataChanged (const QModelIndex & topLeft, const QModelIndex & bottomRight) +pcl::cloud_composer::CloudView::dataChanged (const QModelIndex &, const QModelIndex &) { @@ -283,7 +283,7 @@ pcl::cloud_composer::CloudView::setInteractorStyle (interactor_styles::INTERACTO } void -pcl::cloud_composer::CloudView::selectionCompleted (vtkObject* caller, unsigned long event_id, void* client_data, void* call_data) +pcl::cloud_composer::CloudView::selectionCompleted (vtkObject*, unsigned long, void*, void* call_data) { boost::shared_ptr selected (static_cast (call_data)); @@ -297,7 +297,7 @@ pcl::cloud_composer::CloudView::selectionCompleted (vtkObject* caller, unsigned void -pcl::cloud_composer::CloudView::manipulationCompleted (vtkObject* caller, unsigned long event_id, void* client_data, void* call_data) +pcl::cloud_composer::CloudView::manipulationCompleted (vtkObject*, unsigned long, void*, void* call_data) { boost::shared_ptr manip_event (static_cast (call_data)); @@ -307,4 +307,5 @@ pcl::cloud_composer::CloudView::manipulationCompleted (vtkObject* caller, unsign model_->manipulateClouds (manip_event); } -} \ No newline at end of file +} + diff --git a/apps/cloud_composer/src/commands.cpp b/apps/cloud_composer/src/commands.cpp index 61fa24ff..ecd6d015 100644 --- a/apps/cloud_composer/src/commands.cpp +++ b/apps/cloud_composer/src/commands.cpp @@ -475,12 +475,11 @@ pcl::cloud_composer::DeleteItemCommand::DeleteItemCommand (QList output; @@ -592,4 +591,5 @@ pcl::cloud_composer::MergeCloudCommand::redo () qCritical () << "Removal of items failed in MergeCloudCommand::redo"; } -} \ No newline at end of file +} + diff --git a/apps/cloud_composer/src/item_inspector.cpp b/apps/cloud_composer/src/item_inspector.cpp index 9e769b0b..57b412d2 100644 --- a/apps/cloud_composer/src/item_inspector.cpp +++ b/apps/cloud_composer/src/item_inspector.cpp @@ -47,7 +47,7 @@ pcl::cloud_composer::ItemInspector::setModel (ProjectModel* new_model) } void -pcl::cloud_composer::ItemInspector::selectionChanged (const QModelIndex ¤t, const QModelIndex &) +pcl::cloud_composer::ItemInspector::selectionChanged (const QModelIndex &, const QModelIndex &) { //If we have a model loaded, save its tree state // if (current_item_properties_model_) diff --git a/apps/cloud_composer/src/items/cloud_composer_item.cpp b/apps/cloud_composer/src/items/cloud_composer_item.cpp index db74523d..e647a4c7 100644 --- a/apps/cloud_composer/src/items/cloud_composer_item.cpp +++ b/apps/cloud_composer/src/items/cloud_composer_item.cpp @@ -60,13 +60,13 @@ pcl::cloud_composer::CloudComposerItem::addChild (CloudComposerItem *item_arg) } void -pcl::cloud_composer::CloudComposerItem::paintView (boost::shared_ptr vis) const +pcl::cloud_composer::CloudComposerItem::paintView (boost::shared_ptr) const { qDebug () << "Paint View in Cloud Composer Item - doing nothing"; } void -pcl::cloud_composer::CloudComposerItem::removeFromView (boost::shared_ptr vis) const +pcl::cloud_composer::CloudComposerItem::removeFromView (boost::shared_ptr) const { qDebug () << "Remove from View in Cloud Composer Item - doing nothing"; } diff --git a/apps/cloud_composer/src/merge_selection.cpp b/apps/cloud_composer/src/merge_selection.cpp index c27c474d..3638380c 100644 --- a/apps/cloud_composer/src/merge_selection.cpp +++ b/apps/cloud_composer/src/merge_selection.cpp @@ -55,6 +55,10 @@ pcl::cloud_composer::MergeSelection::performAction (ConstItemList input_data, Po pcl::ExtractIndices filter; pcl::PCLPointCloud2::Ptr merged_cloud (new pcl::PCLPointCloud2); + //To Save the pose of the first original item + Eigen::Vector4f source_origin; + Eigen::Quaternionf source_orientation; + bool pose_found = false; foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys ()) { //If this cloud hasn't been completely selected @@ -72,8 +76,13 @@ pcl::cloud_composer::MergeSelection::performAction (ConstItemList input_data, Po filter.filter (*selected_points); qDebug () << "Original minus indices is "<width; - Eigen::Vector4f source_origin = input_cloud_item->data (ItemDataRole::ORIGIN).value (); - Eigen::Quaternionf source_orientation = input_cloud_item->data (ItemDataRole::ORIENTATION).value (); + + if (!pose_found) + { + source_origin = input_cloud_item->data (ItemDataRole::ORIGIN).value (); + source_orientation = input_cloud_item->data (ItemDataRole::ORIENTATION).value (); + pose_found = true; + } CloudItem* new_cloud_item = new CloudItem (input_cloud_item->text () , original_minus_indices , source_origin @@ -95,11 +104,13 @@ pcl::cloud_composer::MergeSelection::performAction (ConstItemList input_data, Po concatenatePointCloud (*merged_cloud, *input_cloud, *temp_cloud); merged_cloud = temp_cloud; } - + CloudItem* cloud_item = new CloudItem ("Cloud from Selection" - , merged_cloud); + , merged_cloud + , source_origin + , source_orientation); output.append (cloud_item); return output; -} \ No newline at end of file +} diff --git a/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp b/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp index 52909b2d..ad86a060 100644 --- a/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp +++ b/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp @@ -54,18 +54,24 @@ pcl::cloud_composer::RectangularFrustumSelector::OnLeftButtonUp () vtkMapper* mapper = act->actor->GetMapper (); vtkDataSet* data = mapper->GetInput (); vtkPolyData* poly_data = vtkPolyData::SafeDownCast (data); +#if VTK_MAJOR_VERSION > 5 + id_filter->SetInputData (poly_data); +#else id_filter->SetInput (poly_data); +#endif //extract_geometry->SetInput (poly_data); vtkSmartPointer selected = vtkSmartPointer::New (); glyph_filter->SetOutput (selected); glyph_filter->Update (); +#if VTK_MAJOR_VERSION < 6 selected->SetSource (0); +#endif if (selected->GetNumberOfPoints() > 0) { qDebug () << "Selected " << selected->GetNumberOfPoints () << " points."; id_selected_data_map.insert ( QString::fromStdString ((*it).first), selected); - #if VTK_MAJOR_VERSION <= 5 + #if VTK_MAJOR_VERSION < 6 append->AddInput (selected); #else // VTK 6 append->AddInputData (selected); @@ -77,9 +83,12 @@ pcl::cloud_composer::RectangularFrustumSelector::OnLeftButtonUp () append->Update (); vtkSmartPointer all_points = append->GetOutput (); qDebug () << "Allpoints = " <GetNumberOfPoints (); - - selected_mapper->SetInput (all_points); +#if VTK_MAJOR_VERSION < 6 + selected_mapper->SetInput (all_points); +#else + selected_mapper->SetInputData (all_points); +#endif selected_mapper->ScalarVisibilityOff (); vtkIdTypeArray* ids = vtkIdTypeArray::SafeDownCast (all_points->GetPointData ()->GetArray ("OriginalIds")); diff --git a/apps/cloud_composer/src/project_model.cpp b/apps/cloud_composer/src/project_model.cpp index 0ea004cd..744ab2ab 100644 --- a/apps/cloud_composer/src/project_model.cpp +++ b/apps/cloud_composer/src/project_model.cpp @@ -380,7 +380,7 @@ pcl::cloud_composer::ProjectModel::saveSelectedCloudToFile () pcl::PCLPointCloud2::ConstPtr cloud = cloud_to_save->data (ItemDataRole::CLOUD_BLOB).value (); Eigen::Vector4f origin = cloud_to_save->data (ItemDataRole::ORIGIN).value (); Eigen::Quaternionf orientation = cloud_to_save->data (ItemDataRole::ORIENTATION).value (); - int result = pcl::io::savePCDFile (filename.toStdString (), *cloud, origin, orientation ); + pcl::io::savePCDFile (filename.toStdString (), *cloud, origin, orientation ); } @@ -539,7 +539,6 @@ void pcl::cloud_composer::ProjectModel::selectAllItems (QStandardItem* item) { - int num_rows; if (!item) item = this->invisibleRootItem (); else @@ -564,7 +563,6 @@ pcl::cloud_composer::ProjectModel::emitAllStateSignals () emit newCloudFromSelectionAvailable (onlyCloudItemsSelected ()); //Find out which style is active, emit the signal - QMap::iterator itr = selected_style_map_.begin(); foreach (interactor_styles::INTERACTOR_STYLES style, selected_style_map_.keys()) { if (selected_style_map_.value (style)) @@ -578,7 +576,7 @@ pcl::cloud_composer::ProjectModel::emitAllStateSignals () } void -pcl::cloud_composer::ProjectModel::itemSelectionChanged ( const QItemSelection & selected, const QItemSelection & deselected ) +pcl::cloud_composer::ProjectModel::itemSelectionChanged ( const QItemSelection &, const QItemSelection &) { //qDebug () << "Item selection changed!"; //Set all point selected cloud items back to green text, since if they are selected they get changed to white diff --git a/apps/cloud_composer/src/properties_model.cpp b/apps/cloud_composer/src/properties_model.cpp index 83ad52f4..3688caa1 100644 --- a/apps/cloud_composer/src/properties_model.cpp +++ b/apps/cloud_composer/src/properties_model.cpp @@ -128,9 +128,10 @@ pcl::cloud_composer::PropertiesModel::copyProperties (const PropertiesModel* to_ void -pcl::cloud_composer::PropertiesModel::propertyChanged (QStandardItem* property_item) +pcl::cloud_composer::PropertiesModel::propertyChanged (QStandardItem*) { //qDebug () << "Property Changed in properties model"; parent_item_->propertyChanged (); -} \ No newline at end of file +} + diff --git a/apps/cloud_composer/src/toolbox_model.cpp b/apps/cloud_composer/src/toolbox_model.cpp index 558f33d5..d451f073 100644 --- a/apps/cloud_composer/src/toolbox_model.cpp +++ b/apps/cloud_composer/src/toolbox_model.cpp @@ -73,7 +73,7 @@ pcl::cloud_composer::ToolBoxModel::addToolGroup (QString tool_group_name) } void -pcl::cloud_composer::ToolBoxModel::activeProjectChanged(ProjectModel* new_model, ProjectModel* previous_model) +pcl::cloud_composer::ToolBoxModel::activeProjectChanged(ProjectModel* new_model, ProjectModel*) { //Disconnect old project model signal for selection change if (project_model_) @@ -132,7 +132,7 @@ pcl::cloud_composer::ToolBoxModel::toolAction () } void -pcl::cloud_composer::ToolBoxModel::selectedItemChanged ( const QItemSelection & selected, const QItemSelection & deselected ) +pcl::cloud_composer::ToolBoxModel::selectedItemChanged ( const QItemSelection & selected, const QItemSelection &) { updateEnabledTools (selected); } @@ -247,4 +247,4 @@ pcl::cloud_composer::ToolBoxModel::updateEnabledTools (const QItemSelection curr -} \ No newline at end of file +} diff --git a/apps/cloud_composer/tools/sanitize_cloud.cpp b/apps/cloud_composer/tools/sanitize_cloud.cpp index b03c0ef8..edfde181 100644 --- a/apps/cloud_composer/tools/sanitize_cloud.cpp +++ b/apps/cloud_composer/tools/sanitize_cloud.cpp @@ -20,7 +20,7 @@ pcl::cloud_composer::SanitizeCloudTool::~SanitizeCloudTool () } QList -pcl::cloud_composer::SanitizeCloudTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type) +pcl::cloud_composer::SanitizeCloudTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) { QList output; const CloudComposerItem* input_item; @@ -80,4 +80,5 @@ pcl::cloud_composer::SanitizeCloudToolFactory::createToolParameterModel (QObject parameter_model->addProperty ("Keep Organized", false, Qt::ItemIsEditable | Qt::ItemIsEnabled); return parameter_model; -} \ No newline at end of file +} + diff --git a/apps/cloud_composer/tools/voxel_grid_downsample.cpp b/apps/cloud_composer/tools/voxel_grid_downsample.cpp index 08e59207..59ef0987 100644 --- a/apps/cloud_composer/tools/voxel_grid_downsample.cpp +++ b/apps/cloud_composer/tools/voxel_grid_downsample.cpp @@ -22,7 +22,7 @@ pcl::cloud_composer::VoxelGridDownsampleTool::~VoxelGridDownsampleTool () } QList -pcl::cloud_composer::VoxelGridDownsampleTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type) +pcl::cloud_composer::VoxelGridDownsampleTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) { QList output; const CloudComposerItem* input_item; diff --git a/apps/in_hand_scanner/CMakeLists.txt b/apps/in_hand_scanner/CMakeLists.txt index ab1cbaee..a67dd5e2 100644 --- a/apps/in_hand_scanner/CMakeLists.txt +++ b/apps/in_hand_scanner/CMakeLists.txt @@ -1,24 +1,62 @@ -set(SUBSYS_NAME in_hand_scanner) -set(SUBSYS_DESC "In-hand scanner for small objects") -set(SUBSYS_DEPS common features io kdtree apps) -set(SUBSYS_LIBS pcl_common pcl_features pcl_io pcl_kdtree) +set(SUBSUBSYS_NAME in_hand_scanner) +set(SUBSUBSYS_DESC "In-hand scanner for small objects") +set(SUBSUBSYS_DEPS common features io kdtree apps) +set(SUBSUBSYS_LIBS pcl_common pcl_features pcl_io pcl_kdtree) + +################################################################################ +# Qt +if(NOT QT4_FOUND) + set(DEFAULT AUTO_OFF) + set(REASON "Qt4 is required for the in_hand_scanner app!") +else() + set(DEFAULT TRUE) + set(REASON) +endif() + +# OpenGL +if(NOT OPENGL_FOUND AND NOT OPENGL_GLU_FOUND) + set(DEFAULT AUTO_OFF) + set(REASON "OpenGL & GLU are required for the in_hand_scanner app!") +elseif(NOT ${DEFAULT} STREQUAL "AUTO_OFF") + set(DEFAULT TRUE) + set(REASON) +endif() + +#OpenNI +if(NOT OPENNI_FOUND OR NOT BUILD_OPENNI) + set(DEFAULT AUTO_OFF) + set(REASON "OpenNI was not found or was disabled by the user.") +elseif(NOT ${DEFAULT} STREQUAL "AUTO_OFF") + set(DEFAULT TRUE) + set(REASON) +endif() + +# Default to not building for now +if (${DEFAULT} STREQUAL "TRUE") + set(DEFAULT FALSE) +endif() + +pcl_subsubsys_option(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") +pcl_subsubsys_depend(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS Qt4 OpenGL OpenGL_GLU openni) + +pcl_add_doc("${SUBSUBSYS_NAME}") ################################################################################ set(INCS - include/pcl/apps/${SUBSYS_NAME}/boost.h - include/pcl/apps/${SUBSYS_NAME}/common_types.h - include/pcl/apps/${SUBSYS_NAME}/eigen.h - include/pcl/apps/${SUBSYS_NAME}/icp.h - include/pcl/apps/${SUBSYS_NAME}/input_data_processing.h - include/pcl/apps/${SUBSYS_NAME}/integration.h - include/pcl/apps/${SUBSYS_NAME}/mesh_processing.h - include/pcl/apps/${SUBSYS_NAME}/utils.h - include/pcl/apps/${SUBSYS_NAME}/visibility_confidence.h + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/boost.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/common_types.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/eigen.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/icp.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/input_data_processing.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/integration.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/mesh_processing.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/utils.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/visibility_confidence.h" ) set(IMPL_INCS - include/pcl/apps/${SUBSYS_NAME}/impl/common_types.hpp + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/impl/common_types.hpp" ) set(SRCS @@ -35,19 +73,19 @@ set(SRCS ) # Qt -set(MOC_IN_HAND_SCANNER_INC include/pcl/apps/${SUBSYS_NAME}/in_hand_scanner.h) -set(MOC_OPENGL_VIEWER_INC include/pcl/apps/${SUBSYS_NAME}/opengl_viewer.h) -set(MOC_OFFLINE_INTEGRATION_INC include/pcl/apps/${SUBSYS_NAME}/offline_integration.h) +set(MOC_IN_HAND_SCANNER_INC "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/in_hand_scanner.h") +set(MOC_OPENGL_VIEWER_INC "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/opengl_viewer.h") +set(MOC_OFFLINE_INTEGRATION_INC "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/offline_integration.h") -set(MOC_MAIN_WINDOW_INC include/pcl/apps/${SUBSYS_NAME}/main_window.h) -set(MOC_HELP_WINDOW_INC include/pcl/apps/${SUBSYS_NAME}/help_window.h) +set(MOC_MAIN_WINDOW_INC "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/main_window.h") +set(MOC_HELP_WINDOW_INC "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/help_window.h") set(UI_MAIN_WINDOW src/main_window.ui) set(UI_HELP_WINDOW src/help_window.ui) # Offline integration set(OI_INCS - include/pcl/apps/${SUBSYS_NAME}/integration.h - include/pcl/apps/${SUBSYS_NAME}/visibility_confidence.h + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/integration.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/visibility_confidence.h" ) set(OI_SRCS @@ -60,72 +98,43 @@ set(OI_SRCS ################################################################################ -# Default to not building for now -set(DEFAULT FALSE) - -pcl_subsys_option(BUILD app_${SUBSYS_NAME} ${SUBSYS_DESC} ${DEFAULT} ${REASON}) -pcl_subsys_depend(BUILD app_${SUBSYS_NAME} ${SUBSYS_DEPS}) -pcl_add_doc(${SUBSYS_NAME}) - -set(ADDITIONAL_LIBS "") -if(BUILD) - # Qt - if(NOT QT4_FOUND) - message(WARNING "Qt4 is needed for the in_hand_scanner app! It will not be built!") - set(BUILD FALSE) - endif() - - # OpenGL - find_package(OpenGL) - if(OPENGL_FOUND AND OPENGL_GLU_FOUND) - list(APPEND ADDITIONAL_LIBS ${OPENGL_LIBRARIES}) - else() - message(WARNING "OpenGL & GLU are needed for the in_hand_scanner app! It will not be built!") - set(BUILD FALSE) - endif() -endif() - -################################################################################ - -if(BUILD) +if(build) # Qt # http://qtnode.net/wiki/Qt4_with_cmake # http://qt-project.org/quarterly/view/using_cmake_to_build_qt_projects set(QT_USE_QTOPENGL TRUE) - include(${QT_USE_FILE}) - qt4_wrap_cpp(MOC_IN_HAND_SCANNER_SRC ${MOC_IN_HAND_SCANNER_INC}) - qt4_wrap_cpp(MOC_OPENGL_VIEWER_SRC ${MOC_OPENGL_VIEWER_INC} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - qt4_wrap_cpp(MOC_OFFLINE_INTEGRATION_SRC ${MOC_OFFLINE_INTEGRATION_INC} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + include("${QT_USE_FILE}") + qt4_wrap_cpp(MOC_IN_HAND_SCANNER_SRC "${MOC_IN_HAND_SCANNER_INC}") + qt4_wrap_cpp(MOC_OPENGL_VIEWER_SRC "${MOC_OPENGL_VIEWER_INC}" OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + qt4_wrap_cpp(MOC_OFFLINE_INTEGRATION_SRC "${MOC_OFFLINE_INTEGRATION_INC}" OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - qt4_wrap_cpp(MOC_MAIN_WINDOW_SRC ${MOC_MAIN_WINDOW_INC}) - qt4_wrap_cpp(MOC_HELP_WINDOW_SRC ${MOC_HELP_WINDOW_INC}) - qt4_wrap_ui(UI_MAIN_WINDOW_INC ${UI_MAIN_WINDOW}) - qt4_wrap_ui(UI_HELP_WINDOW_INC ${UI_HELP_WINDOW}) + qt4_wrap_cpp(MOC_MAIN_WINDOW_SRC "${MOC_MAIN_WINDOW_INC}") + qt4_wrap_cpp(MOC_HELP_WINDOW_SRC "${MOC_HELP_WINDOW_INC}") + qt4_wrap_ui(UI_MAIN_WINDOW_INC "${UI_MAIN_WINDOW}") + qt4_wrap_ui(UI_HELP_WINDOW_INC "${UI_HELP_WINDOW}") list(APPEND ADDITIONAL_LIBS ${QT_LIBRARIES}) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) # For the ui files + include_directories("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include") # In-hand scanner - list(APPEND INCS ${MOC_IN_HAND_SCANNER_INC} ${MOC_OPENGL_VIEWER_INC} ${MOC_MAIN_WINDOW_INC} ${MOC_HELP_WINDOW_INC} ${UI_MAIN_WINDOW_INC} ${UI_HELP_WINDOW_INC}) - list(APPEND SRCS ${MOC_IN_HAND_SCANNER_SRC} ${MOC_OPENGL_VIEWER_SRC} ${MOC_MAIN_WINDOW_SRC} ${MOC_HELP_WINDOW_SRC}) - - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + list(APPEND INCS "${MOC_IN_HAND_SCANNER_INC}" "${MOC_OPENGL_VIEWER_INC}" "${MOC_MAIN_WINDOW_INC}" "${MOC_HELP_WINDOW_INC}" "${UI_MAIN_WINDOW_INC}" "${UI_HELP_WINDOW_INC}") + list(APPEND SRCS "${MOC_IN_HAND_SCANNER_SRC}" "${MOC_OPENGL_VIEWER_SRC}" "${MOC_MAIN_WINDOW_SRC}" "${MOC_HELP_WINDOW_SRC}") - set(EXE_NAME pcl_${SUBSYS_NAME}) - pcl_add_executable_opt_bundle(${EXE_NAME} ${SUBSYS_NAME} ${SRCS} ${INCS} ${IMPL_INCS}) - target_link_libraries(${EXE_NAME} ${SUBSYS_LIBS} ${ADDITIONAL_LIBS}) + set(EXE_NAME "pcl_${SUBSUBSYS_NAME}") + pcl_add_executable_opt_bundle("${EXE_NAME}" "${SUBSUBSYS_NAME}" ${SRCS} ${INCS} ${IMPL_INCS}) + target_link_libraries("${EXE_NAME}" ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) - pcl_add_includes(${SUBSYS_NAME} ${SUBSYS_NAME} ${INCS}) - pcl_add_includes(${SUBSYS_NAME} ${SUBSYS_NAME}/impl ${IMPL_INCS}) + pcl_add_includes("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${INCS}) + pcl_add_includes("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}/impl" ${IMPL_INCS}) - pcl_make_pkgconfig(${EXE_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" "" "" "" "" "") + pcl_make_pkgconfig("${EXE_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" "" "" "" "" "") # Offline integration - list(APPEND OI_INCS ${MOC_OPENGL_VIEWER_INC} ${MOC_OFFLINE_INTEGRATION_INC}) - list(APPEND OI_SRCS ${MOC_OPENGL_VIEWER_SRC} ${MOC_OFFLINE_INTEGRATION_SRC}) + list(APPEND OI_INCS "${MOC_OPENGL_VIEWER_INC}" "${MOC_OFFLINE_INTEGRATION_INC}") + list(APPEND OI_SRCS "${MOC_OPENGL_VIEWER_SRC}" "${MOC_OFFLINE_INTEGRATION_SRC}") - pcl_add_executable_opt_bundle(pcl_offline_integration ${SUBSYS_NAME} ${OI_SRCS} ${OI_INCS}) - target_link_libraries(pcl_offline_integration ${SUBSYS_LIBS} ${ADDITIONAL_LIBS}) + pcl_add_executable_opt_bundle(pcl_offline_integration "${SUBSUBSYS_NAME}" ${OI_SRCS} ${OI_INCS}) + target_link_libraries(pcl_offline_integration ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) endif() diff --git a/apps/in_hand_scanner/src/opengl_viewer.cpp b/apps/in_hand_scanner/src/opengl_viewer.cpp index e51fbb8f..784e03f0 100644 --- a/apps/in_hand_scanner/src/opengl_viewer.cpp +++ b/apps/in_hand_scanner/src/opengl_viewer.cpp @@ -44,12 +44,13 @@ #include #include -#ifdef __APPLE__ -# include -# include +#include +#ifdef OPENGL_IS_A_FRAMEWORK +# include +# include #else -# include -# include +# include +# include #endif #include diff --git a/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp b/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp index b5ed5bea..7863af4b 100644 --- a/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp +++ b/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp @@ -87,7 +87,7 @@ pcl::apps::DominantPlaneSegmentation::compute_table_plane () if (int (cloud_filtered_->points.size ()) < k_) { - PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %zu points! Aborting.", + PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %lu points! Aborting.", cloud_filtered_->points.size ()); return; } @@ -217,7 +217,7 @@ pcl::apps::DominantPlaneSegmentation::compute_fast (std::vectorpoints.size ()) < k_) { - PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %zu points! Aborting.", + PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %lu points! Aborting.", cloud_filtered_->points.size ()); return; } @@ -588,7 +588,7 @@ pcl::apps::DominantPlaneSegmentation::compute (std::vector if (int (cloud_filtered_->points.size ()) < k_) { - PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %zu points! Aborting.", + PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %lu points! Aborting.", cloud_filtered_->points.size ()); return; } @@ -599,14 +599,14 @@ pcl::apps::DominantPlaneSegmentation::compute (std::vector grid_.setInputCloud (cloud_filtered_); grid_.filter (*cloud_downsampled_); - PCL_INFO ("[DominantPlaneSegmentation] Number of points left after filtering (%f -> %f): %zu out of %zu\n", + PCL_INFO ("[DominantPlaneSegmentation] Number of points left after filtering (%f -> %f): %lu out of %lu\n", min_z_bounds_, max_z_bounds_, cloud_downsampled_->points.size (), input_->points.size ()); // ---[ Estimate the point normals n3d_.setInputCloud (cloud_downsampled_); n3d_.compute (*cloud_normals_); - PCL_INFO ("[DominantPlaneSegmentation] %zu normals estimated. \n", cloud_normals_->points.size ()); + PCL_INFO ("[DominantPlaneSegmentation] %lu normals estimated. \n", cloud_normals_->points.size ()); // ---[ Perform segmentation seg_.setInputCloud (cloud_downsampled_); @@ -681,7 +681,7 @@ pcl::apps::DominantPlaneSegmentation::compute (std::vector cluster_.setIndices (boost::make_shared (cloud_object_indices)); cluster_.extract (clusters2); - PCL_INFO ("[DominantPlaneSegmentation::compute()] Number of clusters found matching the given constraints: %zu.\n", + PCL_INFO ("[DominantPlaneSegmentation::compute()] Number of clusters found matching the given constraints: %lu.\n", clusters2.size ()); clusters.resize (clusters2.size ()); @@ -751,7 +751,7 @@ pcl::apps::DominantPlaneSegmentation::compute_full (std::vectorpoints.size ()) < k_) { - PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %zu points! Aborting.", + PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %lu points! Aborting.", cloud_filtered_->points.size ()); return; } @@ -762,14 +762,14 @@ pcl::apps::DominantPlaneSegmentation::compute_full (std::vector %f): %zu out of %zu\n", + PCL_INFO ("[DominantPlaneSegmentation] Number of points left after filtering&downsampling (%f -> %f): %lu out of %lu\n", min_z_bounds_, max_z_bounds_, cloud_downsampled_->points.size (), input_->points.size ()); // ---[ Estimate the point normals n3d_.setInputCloud (cloud_downsampled_); n3d_.compute (*cloud_normals_); - PCL_INFO ("[DominantPlaneSegmentation] %zu normals estimated. \n", cloud_normals_->points.size ()); + PCL_INFO ("[DominantPlaneSegmentation] %lu normals estimated. \n", cloud_normals_->points.size ()); // ---[ Perform segmentation seg_.setInputCloud (cloud_downsampled_); @@ -842,7 +842,7 @@ pcl::apps::DominantPlaneSegmentation::compute_full (std::vector (cloud_object_indices)); cluster_.extract (clusters2); - PCL_INFO ("[DominantPlaneSegmentation::compute_full()] Number of clusters found matching the given constraints: %zu.\n", + PCL_INFO ("[DominantPlaneSegmentation::compute_full()] Number of clusters found matching the given constraints: %lu.\n", clusters2.size ()); clusters.resize (clusters2.size ()); diff --git a/apps/modeler/CMakeLists.txt b/apps/modeler/CMakeLists.txt old mode 100755 new mode 100644 index 7fe3f7f0..7181cd46 --- a/apps/modeler/CMakeLists.txt +++ b/apps/modeler/CMakeLists.txt @@ -1,70 +1,68 @@ -set(SUBSYS_NAME modeler) -set(SUBSYS_DESC "PCLModeler: PCL based reconstruction platform") -set(SUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search apps) +set(SUBSUBSYS_NAME modeler) +set(SUBSUBSYS_DESC "PCLModeler: PCL based reconstruction platform") +set(SUBSUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search apps) set(REASON "") # Find VTK and QVTK if(VTK_FOUND AND VTK_USE_QVTK) set(DEFAULT TRUE) set(REASON) - set(VTK_USE_FILE ${VTK_USE_FILE} CACHE INTERNAL "VTK_USE_FILE") - include (${VTK_USE_FILE}) + set(VTK_USE_FILE "${VTK_USE_FILE}" CACHE INTERNAL "VTK_USE_FILE") + include("${VTK_USE_FILE}") elseif(NOT VTK_FOUND) - set(DEFAULT FALSE) + set(DEFAULT AUTO_OFF) set(REASON "VTK was not found.") elseif(NOT VTK_USE_QVTK) - set(DEFAULT FALSE) + set(DEFAULT AUTO_OFF) set(REASON "VTK was not built with Qt support.") endif(VTK_FOUND AND VTK_USE_QVTK) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - # Default to not building for now -set(DEFAULT FALSE) +if (${DEFAULT} STREQUAL "TRUE") + set(DEFAULT FALSE) +endif() -PCL_SUBSYS_OPTION(build app_${SUBSYS_NAME} ${SUBSYS_DESC} ${DEFAULT} ${REASON}) -PCL_SUBSYS_DEPEND(build app_${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS vtk) +PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") +PCL_SUBSUBSYS_DEPEND(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS vtk) -PCL_ADD_DOC(${SUBSYS_NAME}) +PCL_ADD_DOC("${SUBSUBSYS_NAME}") if(build) - - include_directories (${CMAKE_CURRENT_BINARY_DIR}) - include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include) + include_directories("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include") # Set Qt files and resources here set(uis main_window.ui) - set(moc_incs include/pcl/apps/${SUBSYS_NAME}/main_window.h - include/pcl/apps/${SUBSYS_NAME}/scene_tree.h - include/pcl/apps/${SUBSYS_NAME}/parameter_dialog.h - include/pcl/apps/${SUBSYS_NAME}/thread_controller.h - include/pcl/apps/${SUBSYS_NAME}/abstract_worker.h - include/pcl/apps/${SUBSYS_NAME}/cloud_mesh_item_updater.h) + set(moc_incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/main_window.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/scene_tree.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/parameter_dialog.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/thread_controller.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/abstract_worker.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_mesh_item_updater.h") set(resources resources/resources.qrc) set(incs ${moc_incs} - include/pcl/apps/${SUBSYS_NAME}/qt.h + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/qt.h" - include/pcl/apps/${SUBSYS_NAME}/dock_widget.h - include/pcl/apps/${SUBSYS_NAME}/abstract_item.h - include/pcl/apps/${SUBSYS_NAME}/render_window.h - include/pcl/apps/${SUBSYS_NAME}/render_window_item.h + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/dock_widget.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/abstract_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/render_window.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/render_window_item.h" - include/pcl/apps/${SUBSYS_NAME}/parameter.h + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/parameter.h" - include/pcl/apps/${SUBSYS_NAME}/cloud_mesh.h - include/pcl/apps/${SUBSYS_NAME}/cloud_mesh_item.h - include/pcl/apps/${SUBSYS_NAME}/channel_actor_item.h - include/pcl/apps/${SUBSYS_NAME}/points_actor_item.h - include/pcl/apps/${SUBSYS_NAME}/normals_actor_item.h - include/pcl/apps/${SUBSYS_NAME}/surface_actor_item.h + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_mesh.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_mesh_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/channel_actor_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/points_actor_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/normals_actor_item.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/surface_actor_item.h" - include/pcl/apps/${SUBSYS_NAME}/icp_registration_worker.h - include/pcl/apps/${SUBSYS_NAME}/voxel_grid_downsample_worker.h - include/pcl/apps/${SUBSYS_NAME}/statistical_outlier_removal_worker.h - include/pcl/apps/${SUBSYS_NAME}/normal_estimation_worker.h - include/pcl/apps/${SUBSYS_NAME}/poisson_worker.h) + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/icp_registration_worker.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/voxel_grid_downsample_worker.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/statistical_outlier_removal_worker.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/normal_estimation_worker.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/poisson_worker.h") set(srcs src/main.cpp @@ -95,8 +93,8 @@ if(build) src/normal_estimation_worker.cpp src/poisson_worker.cpp) - set(impl_incs include/pcl/apps/${SUBSYS_NAME}/impl/parameter.hpp - include/pcl/apps/${SUBSYS_NAME}/impl/scene_tree.hpp) + set(impl_incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/impl/parameter.hpp" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/impl/scene_tree.hpp") # Qt stuff QT4_WRAP_UI(ui_srcs ${uis}) @@ -109,23 +107,22 @@ if(build) SET_SOURCE_FILES_PROPERTIES(${srcs} PROPERTIES OBJECT_DEPENDS "${ui_srcs}") # Generate executable - set(EXE_NAME pcl_${SUBSYS_NAME}) - PCL_ADD_EXECUTABLE(${EXE_NAME} ${SUBSYS_NAME} ${ui_srcs} ${moc_srcs} ${resource_srcs} ${srcs} ${incs} ${impl_incs}) - target_link_libraries(${EXE_NAME} pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search QVTK ${QT_LIBRARIES}) + set(EXE_NAME "pcl_${SUBSUBSYS_NAME}") + PCL_ADD_EXECUTABLE("${EXE_NAME}" "${SUBSUBSYS_NAME}" ${ui_srcs} ${moc_srcs} ${resource_srcs} ${srcs} ${incs} ${impl_incs}) + target_link_libraries("${EXE_NAME}" pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search ${QVTK_LIBRARY} ${QT_LIBRARIES}) # Put the ui in the windows project file - IF (${CMAKE_BUILD_TOOL} MATCHES "msdev") - SET (srcs ${srcs} ${uis}) - ENDIF (${CMAKE_BUILD_TOOL} MATCHES "msdev") - IF (${CMAKE_BUILD_TOOL} MATCHES "devenv") - SET (srcs ${srcs} ${uis}) - ENDIF (${CMAKE_BUILD_TOOL} MATCHES "devenv") + IF("${CMAKE_BUILD_TOOL}" MATCHES "msdev") + LIST(APPEND srcs ${uis}) + ELSEIF("${CMAKE_BUILD_TOOL}" MATCHES "devenv") + LIST(APPEND srcs ${uis}) + ENDIF("${CMAKE_BUILD_TOOL}" MATCHES "msdev") # Install include files - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME} ${incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME}/impl ${impl_incs}) + PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${incs}) + PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}/impl" ${impl_incs}) - PCL_MAKE_PKGCONFIG(${EXE_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" "" "" "" "" "") + PCL_MAKE_PKGCONFIG("${EXE_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" "" "" "" "" "") add_subdirectory(tools) diff --git a/apps/modeler/src/icp_registration_worker.cpp b/apps/modeler/src/icp_registration_worker.cpp index 48dc47af..f3e8ad29 100755 --- a/apps/modeler/src/icp_registration_worker.cpp +++ b/apps/modeler/src/icp_registration_worker.cpp @@ -138,7 +138,7 @@ pcl::modeler::ICPRegistrationWorker::processImpl(CloudMeshItem* cloud_mesh_item) // Set the euclidean distance difference epsilon (criterion 3) icp.setEuclideanFitnessEpsilon (*euclidean_fitness_epsilon_); - icp.setInputCloud(cloud_mesh_item->getCloudMesh()->getCloud()); + icp.setInputSource(cloud_mesh_item->getCloudMesh()->getCloud()); icp.setInputTarget(cloud_); pcl::PointCloud result; icp.align(result); diff --git a/apps/modeler/src/normals_actor_item.cpp b/apps/modeler/src/normals_actor_item.cpp index bb443f5b..fc8bd541 100755 --- a/apps/modeler/src/normals_actor_item.cpp +++ b/apps/modeler/src/normals_actor_item.cpp @@ -137,7 +137,11 @@ pcl::modeler::NormalsActorItem::initImpl() createNormalLines(); vtkSmartPointer mapper = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION < 6 mapper->SetInput(poly_data_); +#else + mapper->SetInputData (poly_data_); +#endif vtkSmartPointer scalars; cloud_mesh_->getColorScalarsFromField(scalars, color_scheme_); @@ -166,8 +170,6 @@ pcl::modeler::NormalsActorItem::updateImpl() scalars->GetRange(minmax); actor_->GetMapper()->SetScalarRange(minmax); - poly_data_->Update(); - return; } diff --git a/apps/modeler/src/points_actor_item.cpp b/apps/modeler/src/points_actor_item.cpp index 2c2474ac..fbd94669 100755 --- a/apps/modeler/src/points_actor_item.cpp +++ b/apps/modeler/src/points_actor_item.cpp @@ -64,13 +64,12 @@ void pcl::modeler::PointsActorItem::initImpl() { poly_data_->SetPoints(cloud_mesh_->getVtkPoints()); - poly_data_->Update(); vtkSmartPointer vertex_glyph_filter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 +#if VTK_MAJOR_VERSION < 6 vertex_glyph_filter->AddInput(poly_data_); #else - vertex_glyph_filter->AddInputData(polydata); + vertex_glyph_filter->AddInputData (poly_data_); #endif vertex_glyph_filter->Update(); @@ -109,8 +108,6 @@ pcl::modeler::PointsActorItem::updateImpl() scalars->GetRange(minmax); actor_->GetMapper()->SetScalarRange(minmax); - poly_data_->Update(); - return; } diff --git a/apps/modeler/src/surface_actor_item.cpp b/apps/modeler/src/surface_actor_item.cpp index cf7b0a5d..6a8a9252 100755 --- a/apps/modeler/src/surface_actor_item.cpp +++ b/apps/modeler/src/surface_actor_item.cpp @@ -69,10 +69,13 @@ pcl::modeler::SurfaceActorItem::initImpl() vtkSmartPointer scalars; cloud_mesh_->getColorScalarsFromField(scalars, color_scheme_); poly_data_->GetPointData ()->SetScalars (scalars); - poly_data_->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION < 6 mapper->SetInput(poly_data_); +#else + mapper->SetInputData (poly_data_); +#endif double minmax[2]; scalars->GetRange(minmax); @@ -108,8 +111,6 @@ pcl::modeler::SurfaceActorItem::updateImpl() scalars->GetRange(minmax); actor_->GetMapper()->SetScalarRange(minmax); - poly_data_->Update(); - return; } diff --git a/apps/optronic_viewer/CMakeLists.txt b/apps/optronic_viewer/CMakeLists.txt index d0dd4432..24f9b5db 100644 --- a/apps/optronic_viewer/CMakeLists.txt +++ b/apps/optronic_viewer/CMakeLists.txt @@ -1,57 +1,72 @@ -set(SUBSYS_NAME optronic_viewer) -set(SUBSYS_DESC "PCL Optronic Viewer") -set(SUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search apps) -set(DEFAULT OFF) -set(REASON "") +set(SUBSUBSYS_NAME optronic_viewer) +set(SUBSUBSYS_DESC "PCL Optronic Viewer") +set(SUBSUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search apps) # Find VTK and QVTK if(VTK_FOUND AND VTK_USE_QVTK) set(DEFAULT TRUE) set(REASON) - set(VTK_USE_FILE ${VTK_USE_FILE} CACHE INTERNAL "VTK_USE_FILE") - include (${VTK_USE_FILE}) + set(VTK_USE_FILE "${VTK_USE_FILE}" CACHE INTERNAL "VTK_USE_FILE") + include("${VTK_USE_FILE}") elseif(NOT VTK_FOUND) - set(DEFAULT FALSE) + set(DEFAULT AUTO_OFF) set(REASON "VTK was not found.") elseif(NOT VTK_USE_QVTK) - set(DEFAULT FALSE) + set(DEFAULT AUTO_OFF) set(REASON "VTK was not built with Qt support.") endif(VTK_FOUND AND VTK_USE_QVTK) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +# Find QT +if(NOT QT_USE_FILE) + set(DEFAULT AUTO_OFF) + set(REASON "Qt was not found.") +elseif(NOT ${DEFAULT} STREQUAL "AUTO_OFF") + set(DEFAULT TRUE) + set(REASON) +endif(NOT QT_USE_FILE) + +# FZAPI +if(FZAPI_FOUND) + set(DEFAULT TRUE) + set(REASON) +elseif(NOT ${DEFAULT} STREQUAL "AUTO_OFF") + set(DEFAULT AUTO_OFF) + set(REASON "FZAPI was not found.") +endif() # Default to not building for now -set(DEFAULT FALSE) +if (${DEFAULT} STREQUAL "TRUE") + set(DEFAULT FALSE) +endif() -PCL_SUBSYS_OPTION(build app_${SUBSYS_NAME} ${SUBSYS_DESC} ${DEFAULT} ${REASON}) -PCL_SUBSYS_DEPEND(build app_${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS vtk) +PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" ${DEFAULT} "${REASON}") +PCL_SUBSUBSYS_DEPEND(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSUBSYS_DEPS} EXT_DEPS vtk) -PCL_ADD_DOC(${SUBSYS_NAME}) +PCL_ADD_DOC("${SUBSUBSYS_NAME}") if(build) - include_directories (${CMAKE_CURRENT_BINARY_DIR}) - include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include) + include_directories("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include") # Set Qt files and resources here # set(uis main_window.ui) - set(moc_incs include/pcl/apps/${SUBSYS_NAME}/main_window.h - include/pcl/apps/${SUBSYS_NAME}/filter_window.h - include/pcl/apps/${SUBSYS_NAME}/openni_grabber.h) -# include/pcl/apps/${SUBSYS_NAME}/scene_tree.h -# include/pcl/apps/${SUBSYS_NAME}/parameter_dialog.h -# include/pcl/apps/${SUBSYS_NAME}/thread_controller.h -# include/pcl/apps/${SUBSYS_NAME}/abstract_worker.h -# include/pcl/apps/${SUBSYS_NAME}/cloud_mesh_item_updater.h) + set(moc_incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/main_window.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/filter_window.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/openni_grabber.h") +# "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/scene_tree.h" +# "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/parameter_dialog.h" +# "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/thread_controller.h" +# "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/abstract_worker.h" +# "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_mesh_item_updater.h") # set(resources resources/resources.qrc) # set(incs ${moc_incs}) - set(incs include/pcl/apps/${SUBSYS_NAME}/qt.h - include/pcl/apps/${SUBSYS_NAME}/openni_grabber.h - include/pcl/apps/${SUBSYS_NAME}/cloud_filter.h - include/pcl/apps/${SUBSYS_NAME}/main_window.h - include/pcl/apps/${SUBSYS_NAME}/filter_window.h) + set(incs "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/qt.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/openni_grabber.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/cloud_filter.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/main_window.h" + "include/pcl/${SUBSYS_NAME}/${SUBSUBSYS_NAME}/filter_window.h") set(srcs src/main.cpp src/cloud_filter.cpp @@ -72,23 +87,22 @@ if(build) # SET_SOURCE_FILES_PROPERTIES(${srcs} PROPERTIES OBJECT_DEPENDS "${ui_srcs}") # Generate executable - set(EXE_NAME pcl_${SUBSYS_NAME}) -# PCL_ADD_EXECUTABLE(${EXE_NAME} ${SUBSYS_NAME} ${ui_srcs} ${moc_srcs} ${resource_srcs} ${srcs} ${incs} ${impl_incs}) - PCL_ADD_EXECUTABLE(${EXE_NAME} ${SUBSYS_NAME} ${moc_srcs} ${srcs} ${incs} ${impl_incs}) - target_link_libraries(${EXE_NAME} pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search QVTK ${QT_LIBRARIES}) + set(EXE_NAME "pcl_${SUBSUBSYS_NAME}") +# PCL_ADD_EXECUTABLE("${EXE_NAME}" "${SUBSUBSYS_NAME}" ${ui_srcs} ${moc_srcs} ${resource_srcs} ${srcs} ${incs} ${impl_incs}) + PCL_ADD_EXECUTABLE("${EXE_NAME}" "${SUBSUBSYS_NAME}" ${moc_srcs} ${srcs} ${incs} ${impl_incs}) + target_link_libraries("${EXE_NAME}" pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search QVTK ${QT_LIBRARIES}) # Put the ui in the windows project file - IF (${CMAKE_BUILD_TOOL} MATCHES "msdev") - SET (srcs ${srcs} ${uis}) - ENDIF (${CMAKE_BUILD_TOOL} MATCHES "msdev") - IF (${CMAKE_BUILD_TOOL} MATCHES "devenv") - SET (srcs ${srcs} ${uis}) - ENDIF (${CMAKE_BUILD_TOOL} MATCHES "devenv") + IF("${CMAKE_BUILD_TOOL}" MATCHES "msdev") + LIST(APPEND srcs ${uis}) + ELSEIF("${CMAKE_BUILD_TOOL}" MATCHES "devenv") + LIST(APPEND srcs ${uis}) + ENDIF("${CMAKE_BUILD_TOOL}" MATCHES "msdev") # Install include files - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME} ${incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME}/impl ${impl_incs}) + PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${incs}) + PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}/impl" ${impl_incs}) - PCL_MAKE_PKGCONFIG(${EXE_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" "" "" "" "" "") + PCL_MAKE_PKGCONFIG("${EXE_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" "" "" "" "" "") endif(build) diff --git a/apps/point_cloud_editor/CMakeLists.txt b/apps/point_cloud_editor/CMakeLists.txt index 5670d762..7c027567 100644 --- a/apps/point_cloud_editor/CMakeLists.txt +++ b/apps/point_cloud_editor/CMakeLists.txt @@ -1,121 +1,119 @@ -SET(SUBSYS_NAME point_cloud_editor) -SET(SUBSYS_DESC "Point Cloud Editor - Simple editor for 3D point clouds") -SET(SUBSYS_DEPS common filters io apps) +SET(SUBSUBSYS_NAME point_cloud_editor) +SET(SUBSUBSYS_DESC "Point Cloud Editor - Simple editor for 3D point clouds") +SET(SUBSUBSYS_DEPS common filters io apps) -SET(MOC_INCS include/pcl/apps/${SUBSYS_NAME}/cloudEditorWidget.h - include/pcl/apps/${SUBSYS_NAME}/mainWindow.h - include/pcl/apps/${SUBSYS_NAME}/denoiseParameterForm.h - include/pcl/apps/${SUBSYS_NAME}/statisticsDialog.h +SET(MOC_INCS "include/pcl/apps/${SUBSUBSYS_NAME}/cloudEditorWidget.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/mainWindow.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/denoiseParameterForm.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/statisticsDialog.h" ) SET(RSRC resources/pceditor_resources.qrc) SET(INCS ${MOC_INCS} - include/pcl/apps/${SUBSYS_NAME}/cloud.h - include/pcl/apps/${SUBSYS_NAME}/cloudTransformTool.h - include/pcl/apps/${SUBSYS_NAME}/command.h - include/pcl/apps/${SUBSYS_NAME}/commandQueue.h - include/pcl/apps/${SUBSYS_NAME}/common.h - include/pcl/apps/${SUBSYS_NAME}/copyBuffer.h - include/pcl/apps/${SUBSYS_NAME}/copyCommand.h - include/pcl/apps/${SUBSYS_NAME}/cutCommand.h - include/pcl/apps/${SUBSYS_NAME}/deleteCommand.h - include/pcl/apps/${SUBSYS_NAME}/denoiseCommand.h - include/pcl/apps/${SUBSYS_NAME}/localTypes.h - include/pcl/apps/${SUBSYS_NAME}/pasteCommand.h - include/pcl/apps/${SUBSYS_NAME}/select1DTool.h - include/pcl/apps/${SUBSYS_NAME}/select2DTool.h - include/pcl/apps/${SUBSYS_NAME}/selection.h - include/pcl/apps/${SUBSYS_NAME}/selectionTransformTool.h - include/pcl/apps/${SUBSYS_NAME}/statistics.h - include/pcl/apps/${SUBSYS_NAME}/toolInterface.h - include/pcl/apps/${SUBSYS_NAME}/trackball.h - include/pcl/apps/${SUBSYS_NAME}/transformCommand.h + "include/pcl/apps/${SUBSUBSYS_NAME}/cloud.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/cloudTransformTool.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/command.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/commandQueue.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/common.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/copyBuffer.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/copyCommand.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/cutCommand.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/deleteCommand.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/denoiseCommand.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/localTypes.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/pasteCommand.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/select1DTool.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/select2DTool.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/selection.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/selectionTransformTool.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/statistics.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/toolInterface.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/trackball.h" + "include/pcl/apps/${SUBSUBSYS_NAME}/transformCommand.h" ) -SET(SRCS src/main.cpp - src/mainWindow.cpp - src/commandQueue.cpp - src/selection.cpp - src/copyBuffer.cpp - src/deleteCommand.cpp - src/cutCommand.cpp - src/pasteCommand.cpp - src/cloud.cpp - src/cloudEditorWidget.cpp - src/cloudTransformTool.cpp - src/select1DTool.cpp - src/select2DTool.cpp - src/selectionTransformTool.cpp - src/transformCommand.cpp - src/common.cpp - src/denoiseCommand.cpp - src/statistics.cpp - src/statisticsDialog.cpp - src/trackball.cpp - src/denoiseParameterForm.cpp +SET(SRCS src/main.cpp + src/mainWindow.cpp + src/commandQueue.cpp + src/selection.cpp + src/copyBuffer.cpp + src/deleteCommand.cpp + src/cutCommand.cpp + src/pasteCommand.cpp + src/cloud.cpp + src/cloudEditorWidget.cpp + src/cloudTransformTool.cpp + src/select1DTool.cpp + src/select2DTool.cpp + src/selectionTransformTool.cpp + src/transformCommand.cpp + src/common.cpp + src/denoiseCommand.cpp + src/statistics.cpp + src/statisticsDialog.cpp + src/trackball.cpp + src/denoiseParameterForm.cpp ) IF(NOT QT4_FOUND) - SET(DEFAULT FALSE) + SET(DEFAULT AUTO_OFF) SET(REASON "Qt4 was not found.") ELSE(NOT QT4_FOUND) SET(DEFAULT TRUE) SET(REASON) ENDIF(NOT QT4_FOUND) + # Find OpenGL -find_package(OpenGL) IF(NOT OPENGL_FOUND) - SET(DEFAULT FALSE) + SET(DEFAULT AUTO_OFF) SET(REASON "OpenGL was not found.") -ELSE(NOT OPENGL_FOUND) +ELSEIF(NOT ${DEFAULT} STREQUAL "AUTO_OFF") SET(DEFAULT TRUE) SET(REASON) ENDIF(NOT OPENGL_FOUND) # Default to not building for now -set(DEFAULT FALSE) -SET(REASON "") +if (${DEFAULT} STREQUAL "TRUE") + set(DEFAULT FALSE) +endif() -PCL_SUBSYS_OPTION(BUILD app_${SUBSYS_NAME} ${SUBSYS_DESC} ${DEFAULT} ${REASON}) -PCL_SUBSYS_DEPEND(BUILD app_${SUBSYS_NAME} ${SUBSYS_DEPS}) -PCL_ADD_DOC(${SUBSYS_NAME}) +PCL_SUBSUBSYS_OPTION(BUILD "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") +PCL_SUBSUBSYS_DEPEND(BUILD "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${SUBSYS_DEPS}) +PCL_ADD_DOC(${SUBSUBSYS_NAME}) IF(BUILD) - - INCLUDE(${QT_USE_FILE}) + INCLUDE("${QT_USE_FILE}") SET(QT_USE_QTOPENGL TRUE) #QT4_WRAP_CPP(MOC_SRCS ${MOC_INCS}) QT4_WRAP_CPP(MOC_SRCS ${MOC_INCS} OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED) QT4_ADD_RESOURCES(RESOURCES_SRCS ${RSRC}) - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${QT_QT_INCLUDE_DIR} - ${QT_QTOPENGL_INCLUDE_DIR} - ) - - SET(EXE_NAME pcl_${SUBSYS_NAME}) - PCL_ADD_EXECUTABLE(${EXE_NAME} - ${SUBSYS_NAME} - ${SRCS} - ${RESOURCES_SRCS} - ${MOC_SRCS} - ${INCS} - ) + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${QT_QTOPENGL_INCLUDE_DIR}" + ) - TARGET_LINK_LIBRARIES(${EXE_NAME} - ${QT_LIBRARIES} - ${QT_QTOPENGL_LIBRARY} - ${OPENGL_LIBRARIES} - ${BOOST_LIBRARIES} - pcl_common - pcl_io - pcl_filters - ) + SET(EXE_NAME "pcl_${SUBSUBSYS_NAME}") + PCL_ADD_EXECUTABLE("${EXE_NAME}" + "${SUBSUBSYS_NAME}" + ${SRCS} + ${RESOURCES_SRCS} + ${MOC_SRCS} + ${INCS} + ) - PCL_ADD_INCLUDES(${SUBSYS_NAME} ${SUBSYS_NAME} ${INCS}) - PCL_MAKE_PKGCONFIG(${EXE_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" "" "" "" "" "") + TARGET_LINK_LIBRARIES("${EXE_NAME}" + ${QT_LIBRARIES} + ${QT_QTOPENGL_LIBRARY} + ${OPENGL_LIBRARIES} + ${BOOST_LIBRARIES} + pcl_common + pcl_io + pcl_filters + ) + PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSYS_NAME}/${SUBSUBSYS_NAME}" ${INCS}) + PCL_MAKE_PKGCONFIG("${EXE_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" "" "" "" "" "") ENDIF(BUILD) diff --git a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cutCommand.h b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cutCommand.h index 882171c7..7c79e248 100644 --- a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cutCommand.h +++ b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cutCommand.h @@ -93,13 +93,6 @@ class CutCommand : public Command assert(false); return (*this); } - /// The copy buffer which backs up the points removed from the cloud. - CopyBuffer cut_cloud_buffer_; - - /// a selection which backs up the index of the points cut in the - /// original cloud. - Selection cut_selection_; - /// A shared pointer pointing to the selection object. SelectionPtr selection_ptr_; @@ -109,6 +102,13 @@ class CutCommand : public Command /// a pointer pointing to the copy buffer. CopyBufferPtr copy_buffer_ptr_; + /// a selection which backs up the index of the points cut in the + /// original cloud. + Selection cut_selection_; + + /// The copy buffer which backs up the points removed from the cloud. + CopyBuffer cut_cloud_buffer_; + }; #endif // CUT_COMMAND_H_ diff --git a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/deleteCommand.h b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/deleteCommand.h index d41fc0d7..e2a94a58 100644 --- a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/deleteCommand.h +++ b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/deleteCommand.h @@ -89,18 +89,18 @@ class DeleteCommand : public Command assert(false); return (*this); } - /// a copy buffer which backs up the points deleted from the cloud. - CopyBuffer deleted_cloud_buffer_; + /// a pointer pointing to the cloud + CloudPtr cloud_ptr_; + + /// A shared pointer pointing to the selection object. + SelectionPtr selection_ptr_; /// a selection which backs up the index of the deleted points in the /// original cloud. Selection deleted_selection_; - /// A shared pointer pointing to the selection object. - SelectionPtr selection_ptr_; - - /// a pointer pointing to the cloud - CloudPtr cloud_ptr_; + /// a copy buffer which backs up the points deleted from the cloud. + CopyBuffer deleted_cloud_buffer_; }; #endif // DELETE_COMMAND_H_ diff --git a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/pasteCommand.h b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/pasteCommand.h index d43e6c04..5a87532c 100644 --- a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/pasteCommand.h +++ b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/pasteCommand.h @@ -92,10 +92,8 @@ class PasteCommand : public Command assert(false); return (*this); } - /// The size of the cloud before new points are pasted. This value is used - /// to mark the point where points were added to the cloud. In order to - /// support undo, one only has to resize the cloud using this value. - unsigned int prev_cloud_size_; + /// a pointer pointing to the copy buffer. + ConstCopyBufferPtr copy_buffer_ptr_; /// A shared pointer pointing to the selection object. SelectionPtr selection_ptr_; @@ -103,7 +101,9 @@ class PasteCommand : public Command /// a pointer pointing to the cloud CloudPtr cloud_ptr_; - /// a pointer pointing to the copy buffer. - ConstCopyBufferPtr copy_buffer_ptr_; + /// The size of the cloud before new points are pasted. This value is used + /// to mark the point where points were added to the cloud. In order to + /// support undo, one only has to resize the cloud using this value. + unsigned int prev_cloud_size_; }; #endif // PASTE_COMMAND_H_ diff --git a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/transformCommand.h b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/transformCommand.h index 80a14539..12e65612 100644 --- a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/transformCommand.h +++ b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/transformCommand.h @@ -92,6 +92,14 @@ class TransformCommand : public Command void applyTransform(ConstSelectionPtr sel_ptr); + /// pointers to constructor params + ConstSelectionPtr selection_ptr_; + + /// a pointer poiting to the cloud + CloudPtr cloud_ptr_; + + float translate_x_, translate_y_, translate_z_; + /// An internal selection object used to perform undo SelectionPtr internal_selection_ptr_; @@ -99,14 +107,6 @@ class TransformCommand : public Command /// of the selected points float transform_matrix_[MATRIX_SIZE]; - float translate_x_, translate_y_, translate_z_; - - /// pointers to constructor params - ConstSelectionPtr selection_ptr_; - - /// a pointer poiting to the cloud - CloudPtr cloud_ptr_; - /// The transform matrix of the cloud used by this command float cloud_matrix_[MATRIX_SIZE]; /// The inverted transform matrix of the cloud used by this command diff --git a/apps/point_cloud_editor/src/cloudEditorWidget.cpp b/apps/point_cloud_editor/src/cloudEditorWidget.cpp index 7a6e6330..c6a90a7e 100644 --- a/apps/point_cloud_editor/src/cloudEditorWidget.cpp +++ b/apps/point_cloud_editor/src/cloudEditorWidget.cpp @@ -42,7 +42,15 @@ #include #include #include -#include + +#include + +#ifdef OPENGL_IS_A_FRAMEWORK +# include +#else +# include +#endif + #include #include #include diff --git a/apps/point_cloud_editor/src/statisticsDialog.cpp b/apps/point_cloud_editor/src/statisticsDialog.cpp index 74fdfe82..5d5edfe3 100644 --- a/apps/point_cloud_editor/src/statisticsDialog.cpp +++ b/apps/point_cloud_editor/src/statisticsDialog.cpp @@ -40,7 +40,7 @@ #include -StatisticsDialog::StatisticsDialog(QWidget *parent) +StatisticsDialog::StatisticsDialog(QWidget *) { button_box_ = new QDialogButtonBox; button_box_->addButton(tr("Hide"), QDialogButtonBox::AcceptRole); diff --git a/apps/src/convolve.cpp b/apps/src/convolve.cpp index 1ee96235..050a206b 100644 --- a/apps/src/convolve.cpp +++ b/apps/src/convolve.cpp @@ -64,7 +64,7 @@ main (int argc, char ** argv) { int viewport_source, viewport_convolved = 0; int direction = -1; - int nb_threads = 0; + int nb_threads = 1; char border_policy = 'Z'; double threshold = 0.001; pcl::filters::Convolution convolution; @@ -116,7 +116,20 @@ main (int argc, char ** argv) { if (nb_threads <= 0) nb_threads = 1; +#ifndef _OPENMP + if (nb_threads > 1) + { + pcl::console::print_info ("OpenMP not activated. Number of threads: 1\n"); + nb_threads = 1; + } +#endif + } +#ifdef _OPENMP + else + { + nb_threads = omp_get_num_procs(); } +#endif convolution.setNumberOfThreads (nb_threads); // borders policy if any @@ -188,6 +201,12 @@ main (int argc, char ** argv) } } convolved_label << pcl::getTime () - t0 << "s"; +#ifdef _OPENMP + convolved_label << "\ncpu cores: " << omp_get_num_procs() << " "; +#else + convolved_label << "\n"; +#endif + convolved_label << "threads: " << nb_threads; // Display boost::shared_ptr viewer (new pcl::visualization::PCLVisualizer ("Convolution")); // viewport stuff diff --git a/apps/src/grabcut_2d.cpp b/apps/src/grabcut_2d.cpp new file mode 100644 index 00000000..67bbe82e --- /dev/null +++ b/apps/src/grabcut_2d.cpp @@ -0,0 +1,565 @@ +#include +#include +#include +#include +#include +#include +#include + +#ifdef GLUT_IS_A_FRAMEWORK +#include +#else +#include +#if defined (FREEGLUT) +#include +#elif defined (GLUI_OPENGLUT) +#include +#endif +#endif + +class GrabCutHelper : public pcl::GrabCut +{ + using pcl::GrabCut::n_links_; + using pcl::GrabCut::graph_; + using pcl::GrabCut::indices_; + using pcl::GrabCut::hard_segmentation_; + using pcl::GrabCut::width_; + using pcl::GrabCut::height_; + using pcl::GrabCut::graph_nodes_; + using pcl::GrabCut::L_; + using pcl::GrabCut::K_; + using pcl::GrabCut::GMM_component_; + using pcl::GrabCut::input_; + + public: + typedef boost::shared_ptr Ptr; + typedef boost::shared_ptr ConstPtr; + + GrabCutHelper (uint32_t K = 5, float lambda = 50.f) + : pcl::GrabCut (K, lambda) + {} + + ~GrabCutHelper () + { } + + void + setInputCloud (const pcl::PointCloud::ConstPtr& cloud); + void + setBackgroundPointsIndices (const pcl::PointIndices::ConstPtr& point_indices); + void + setBackgroundPointsIndices (int x1, int y1, int x2, int y2); + void + setTrimap(int x1, int y1, int x2, int y2, const pcl::segmentation::grabcut::TrimapValue& t); + void + refine (); + int + refineOnce (); + void + fitGMMs (); + void + display (int display_type); + void + overlayAlpha (); + + private: + void + buildImages (); + + // Clouds of various variables that can be displayed for debugging. + pcl::PointCloud::Ptr n_links_image_; + pcl::segmentation::grabcut::Image::Ptr t_links_image_; + pcl::segmentation::grabcut::Image::Ptr gmm_image_; + pcl::PointCloud::Ptr alpha_image_; + + int image_height_1_; + int image_width_1_; +}; + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::setInputCloud (const pcl::PointCloud::ConstPtr& cloud) +{ + pcl::GrabCut::setInputCloud (cloud); + // Reset clouds + n_links_image_.reset (new pcl::PointCloud (cloud->width, cloud->height, 0)); + t_links_image_.reset (new pcl::segmentation::grabcut::Image (cloud->width, cloud->height)); + gmm_image_.reset (new pcl::segmentation::grabcut::Image (cloud->width, cloud->height)); + alpha_image_.reset (new pcl::PointCloud (cloud->width, cloud->height, 0)); + image_height_1_ = cloud->height-1; + image_width_1_ = cloud->width-1; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::setBackgroundPointsIndices (const pcl::PointIndices::ConstPtr& point_indices) +{ + pcl::GrabCut::setBackgroundPointsIndices (point_indices); + buildImages (); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::setBackgroundPointsIndices (int x1, int y1, int x2, int y2) +{ + pcl::PointIndices::Ptr point_indices (new pcl::PointIndices); + point_indices->indices.reserve (input_->size ()); + if (x1 > x2) std::swap (x1, x2); + if (y1 > y2) std::swap (y1, y2); + for (int y = std::max (y1, 0); y <= std::min (static_cast (input_->height -1), y2); ++y) + for (int x = std::max (x1, 0); x <= std::min (static_cast (input_->width -1), x2); ++x) + point_indices->indices.push_back (y * input_->width + x); + setBackgroundPointsIndices (point_indices); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::setTrimap(int x1, int y1, int x2, int y2, const pcl::segmentation::grabcut::TrimapValue& t) +{ + using namespace pcl::segmentation::grabcut; + if (x1 > x2) std::swap (x1, x2); + if (y1 > y2) std::swap (y1, y2); + for (int y = std::max (y1, 0); y <= std::min (static_cast (image_height_1_), y2); ++y) + for (int x = std::max (x1, 0); x <= std::min (static_cast (image_width_1_), x2); ++x) + { + std::size_t idx = y * input_->width + x; + trimap_[idx] = TrimapUnknown; + // Immediately set the segmentation as well so that the display will update. + if (t == TrimapForeground) + hard_segmentation_[idx] = SegmentationForeground; + else if (t == TrimapBackground) + hard_segmentation_[idx] = SegmentationBackground; + } + + // Build debugging images + buildImages(); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::refine () +{ +// boost::lock_guard lock (refine_mutex); + pcl::GrabCut::refine (); + buildImages (); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +int +GrabCutHelper::refineOnce () +{ + // boost::lock_guard lock (refine_once_mutex); + int result = pcl::GrabCut::refineOnce (); + buildImages (); + return (result); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::fitGMMs () +{ +// boost::lock_guard lock (fit_gmms_mutex); + pcl::GrabCut::fitGMMs (); + buildImages (); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::buildImages () +{ + using namespace pcl::segmentation::grabcut; + memset (&n_links_image_->points[0], 0, sizeof (float) * n_links_image_->size ()); + for (int y = 0; y < static_cast (image_->height); ++y) + { + for (int x = 0; x < static_cast (image_->width); ++x) + { + std::size_t index = y * image_->width + x; + + if (x > 0 && y < image_height_1_) + { + (*n_links_image_)(x,y) += n_links_[index].weights[0]; + (*n_links_image_)(x-1,y+1) += n_links_[index].weights[0]; + } + + if (y < image_height_1_) + { + (*n_links_image_)(x,y) += n_links_[index].weights[1]; + (*n_links_image_)(x,y+1) += n_links_[index].weights[1]; + } + + if (x < image_width_1_ && y < image_height_1_) + { + (*n_links_image_)(x,y) += n_links_[index].weights[2]; + (*n_links_image_)(x+1,y+1) += n_links_[index].weights[2]; + } + + if (x < image_width_1_) + { + (*n_links_image_)(x,y) += n_links_[index].weights[3]; + (*n_links_image_)(x+1,y) += n_links_[index].weights[3]; + } + + // TLinks cloud + pcl::segmentation::grabcut::Color &tlink_point = t_links_image_->points[index]; + pcl::segmentation::grabcut::Color &gmm_point = gmm_image_->points[index]; + float &alpha_point = alpha_image_->points[index]; + double red = pow (graph_.getSourceEdgeCapacity (index)/L_, 0.25); // red + double green = pow (graph_.getTargetEdgeCapacity (index)/L_, 0.25); // green + tlink_point.r = static_cast (red); + tlink_point.g = static_cast (green); + gmm_point.b = tlink_point.b = 0; + // GMM cloud and Alpha cloud + if (hard_segmentation_[index] == SegmentationForeground) + { + //assert (static_cast(GMM_component_[index]+1)/static_cast (K_) < 1.f); + gmm_point.r = static_cast(GMM_component_[index]+1)/static_cast (K_); + alpha_point = 0; + } + else + { + gmm_point.g = static_cast(GMM_component_[index]+1)/static_cast (K_); + alpha_point = 0.75; + } + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::display (int display_type) +{ + switch (display_type) + { + case 0: + glDrawPixels (image_->width, image_->height, GL_RGB, GL_FLOAT, &(image_->points[0])); + break; + + case 1: + glDrawPixels (gmm_image_->width, gmm_image_->height, GL_RGB, GL_FLOAT, &(gmm_image_->points[0])); + break; + + case 2: + glDrawPixels (n_links_image_->width, n_links_image_->height, GL_LUMINANCE, GL_FLOAT, &(n_links_image_->points[0])); + break; + + case 3: + glDrawPixels (t_links_image_->width, t_links_image_->height, GL_RGB, GL_FLOAT, &(t_links_image_->points[0])); + break; + + default: + // Do nothing + break; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void +GrabCutHelper::overlayAlpha () +{ + glDrawPixels (alpha_image_->width, alpha_image_->height, GL_ALPHA, GL_FLOAT, &(alpha_image_->points[0])); +} + +/* GUI interface */ +int display_type = 0; +bool show_mask = false; +bool initialized = false; +// 2D stuff +int xstart, ystart, xend, yend; +bool box = false; +bool left = false, right = false; +bool refining_ = false; +uint32_t width, height; +GrabCutHelper grabcut; +pcl::segmentation::grabcut::Image::Ptr display_image; + +///////////////////////////////////////////////////////////////////////////////////////////// +void +display () +{ + glClear(GL_COLOR_BUFFER_BIT); + + if (display_type == -1) + glDrawPixels (display_image->width, display_image->height, GL_RGB, GL_FLOAT, &(display_image->points[0])); + else + grabcut.display (display_type); + + if (show_mask) + { + grabcut.overlayAlpha (); + } + + if (box) + { + glColor4f( 1, 1, 1, 1 ); + glBegin( GL_LINE_LOOP ); + glVertex2d( xstart, ystart ); + glVertex2d( xstart, yend ); + glVertex2d( xend, yend ); + glVertex2d( xend, ystart ); + glEnd(); + } + + glFlush(); + glutSwapBuffers(); +} + +///////////////////////////////////////////////////////////////////////// +void +idle_callback () +{ + int changed = 0; + + if (refining_) + { + changed = grabcut.refineOnce (); + glutPostRedisplay (); + } + + if (!changed) + { + refining_ = false; + glutIdleFunc (NULL); + } +} + +///////////////////////////////////////////////////////////////////////// +void +motion_callback (int x, int y) +{ + y = height - y; + + if (box == true) + { + xend = x; yend = y; + glutPostRedisplay (); + } + + if (initialized) + { + if (left) + grabcut.setTrimap (x-2,y-2,x+2,y+2,pcl::segmentation::grabcut::TrimapForeground); + + if (right) + grabcut.setTrimap (x-2,y-2,x+2,y+2,pcl::segmentation::grabcut::TrimapForeground); + + glutPostRedisplay (); + } +} + +void +mouse_callback (int button, int state, int x, int y) +{ + y = height - y; + + switch (button) + { + case GLUT_LEFT_BUTTON: + if (state==GLUT_DOWN) + { + left = true; + + if (!initialized) + { + xstart = x; ystart = y; + box = true; + } + } + + if (state==GLUT_UP) + { + left = false; + + if (initialized) + { + grabcut.refineOnce (); + glutPostRedisplay (); + } + else + { + xend = x; yend = y; + grabcut.setBackgroundPointsIndices (xstart, ystart, xend, yend); + box = false; + initialized = true; + show_mask = true; + glutPostRedisplay (); + } + } + break; + + case GLUT_RIGHT_BUTTON: + if (state==GLUT_DOWN) + { + right = true; + } + if (state==GLUT_UP) + { + right = false; + + if (initialized) + { + grabcut.refineOnce (); + glutPostRedisplay (); + } + } + break; + + default: + break; + } +} + +///////////////////////////////////////////////////////////////////////// +void +keyboard_callback (unsigned char key, int, int) +{ + switch (key) + { + case ' ': // space bar show/hide alpha mask + show_mask = !show_mask; + break; + case '0': case 'i': case 'I':// choose the RGB image + display_type = 0; + break; + case '1': case 'g': case 'G':// choose GMM index mask + display_type = 1; + break; + case '2': case 'n': case 'N': // choose N-Link mask + display_type = 2; + break; + case '3': case 't': case 'T': // choose T-Link mask + display_type = 3; + break; + case 'r': // run GrabCut refinement + refining_ = true; + glutIdleFunc (idle_callback); + break; + case 'o': // run one step of GrabCut refinement + grabcut.refineOnce (); + glutPostRedisplay (); + break; + case 'l': // rerun the Orchard-Bowman GMM clustering + grabcut.fitGMMs (); + glutPostRedisplay (); + break; + // case 's': case 'S': + // save (); + // break; + case 'q': case 'Q': +#if defined (FREEGLUT) || defined (GLUI_OPENGLUT) + glutLeaveMainLoop (); +#else + exit (0); +#endif + break; + case 27: + refining_ = false; + glutIdleFunc(NULL); + default: + break; + } + glutPostRedisplay (); +} + +/////////////////////////////////////////////////////////////////////////////////// +int main (int argc, char** argv) +{ + // Parse the command line arguments for .pcd files + std::vector parsed_file_indices = pcl::console::parse_file_extension_argument (argc, argv, ".pcd"); + if (parsed_file_indices.empty ()) + { + pcl::console::print_error ("Need at least an input PCD file (e.g. scene.pcd) to continue!\n\n"); + pcl::console::print_info ("Ideally, need an input file, and two output PCD files, e.g., object.pcd, background.pcd\n"); + return (-1); + } + + std::string object_file = "object.pcd", background_file = "background.pcd"; + if (parsed_file_indices.size () >= 3) + background_file = argv[parsed_file_indices[2]]; + if (parsed_file_indices.size () >= 2) + object_file = argv[parsed_file_indices[1]]; + + pcl::PCDReader reader; + // Test the header + pcl::PCLPointCloud2 dummy; + reader.readHeader (argv[parsed_file_indices[0]], dummy); + pcl::PointCloud::Ptr scene (new pcl::PointCloud); + if (pcl::getFieldIndex (dummy, "rgba") != -1) + { + if (pcl::io::loadPCDFile (argv[parsed_file_indices[0]], *scene) < 0) + { + pcl::console::print_error (stderr, "[error]\n"); + return (-2); + } + } + else + if (pcl::getFieldIndex (dummy, "rgb") != -1) + { + if (pcl::io::loadPCDFile (argv[parsed_file_indices[0]], *scene) < 0) + { + pcl::console::print_error (stderr, "[error]\n"); + return (-2); + } + } + else + { + pcl::console::print_error (stderr, "[No RGB data found!]\n"); + return (-1); + } + + if (scene->isOrganized ()) + { + pcl::console::print_highlight ("Enabling 2D image viewer mode.\n"); + } + + + width = scene->width; + height = scene->height; + + display_type = -1; + + display_image.reset (new pcl::segmentation::grabcut::Image (scene->width, scene->height)); + pcl::PointCloud::Ptr tmp (new pcl::PointCloud (scene->width, scene->height)); + + if (scene->isOrganized ()) + { + pcl::uint32_t height_1 = scene->height -1; + for (std::size_t i = 0; i < scene->height; ++i) + { + for (std::size_t j = 0; j < scene->width; ++j) + { + const pcl::PointXYZRGB &p = (*scene) (j,i); + std::size_t reverse_index = (height_1-i) * scene->width + j; + display_image->points[reverse_index].r = static_cast (p.r) / 255.0; + display_image->points[reverse_index].g = static_cast (p.g) / 255.0; + display_image->points[reverse_index].b = static_cast (p.b) / 255.0; + tmp->points[reverse_index] = p; + } + } + } + + grabcut.setInputCloud (tmp); + + glutInit (&argc,argv); + glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); + + glutInitWindowSize (width, height); + glutInitWindowPosition (100,100); + + glutCreateWindow ("GrabCut"); + + glOrtho (0,width,0,height,-1,1); + + //set the background color to black (RGBA) + glClearColor(0.0,0.0,0.0,0.0); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + glutDisplayFunc (display); + glutMouseFunc (mouse_callback); + glutMotionFunc (motion_callback); + glutKeyboardFunc (keyboard_callback); + + glutMainLoop (); + + return (0); +} diff --git a/apps/src/ni_linemod.cpp b/apps/src/ni_linemod.cpp index a61c2fdc..9e436a2b 100644 --- a/apps/src/ni_linemod.cpp +++ b/apps/src/ni_linemod.cpp @@ -323,7 +323,7 @@ class NILinemod vector label_indices; vector boundary_indices; mps_.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices); - PCL_DEBUG ("Number of planar regions detected: %zu for a cloud of %zu points and %zu normals.\n", regions.size (), search_.getInputCloud ()->points.size (), normal_cloud->points.size ()); + PCL_DEBUG ("Number of planar regions detected: %lu for a cloud of %lu points and %lu normals.\n", regions.size (), search_.getInputCloud ()->points.size (), normal_cloud->points.size ()); double max_dist = numeric_limits::max (); // Compute the distances from all the planar regions to the picked point, and select the closest region @@ -428,7 +428,7 @@ class NILinemod PlanarRegion refined_region; pcl::approximatePolygon (region, refined_region, 0.01, false, true); - PCL_INFO ("Planar region: %zu points initial, %zu points after refinement.\n", region.getContour ().size (), refined_region.getContour ().size ()); + PCL_INFO ("Planar region: %lu points initial, %lu points after refinement.\n", region.getContour ().size (), refined_region.getContour ().size ()); cloud_viewer_.addPolygon (refined_region, 0.0, 0.0, 1.0, "refined_region"); cloud_viewer_.setShapeRenderingProperties (visualization::PCL_VISUALIZER_LINE_WIDTH, 10, "refined_region"); diff --git a/apps/src/ni_trajkovic.cpp b/apps/src/ni_trajkovic.cpp new file mode 100644 index 00000000..e497a272 --- /dev/null +++ b/apps/src/ni_trajkovic.cpp @@ -0,0 +1,249 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2012-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, O R PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + * + */ + +#define SHOW_FPS 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace pcl; +typedef PointXYZRGBA PointT; +typedef PointXYZI KeyPointT; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class TrajkovicDemo +{ + public: + typedef PointCloud Cloud; + typedef Cloud::Ptr CloudPtr; + typedef Cloud::ConstPtr CloudConstPtr; + + TrajkovicDemo (Grabber& grabber, bool enable_3d) + : cloud_viewer_ ("TRAJKOVIC 3D Keypoints -- PointCloud") + , grabber_ (grabber) + , image_viewer_ ("TRAJKOVIC 3D Keypoints -- Image") + , enable_3d_ (enable_3d) + { + } + + ///////////////////////////////////////////////////////////////////////// + void + cloud_callback_3d (const CloudConstPtr& cloud) + { + FPS_CALC ("cloud callback"); + boost::mutex::scoped_lock lock (cloud_mutex_); + cloud_ = cloud; + + // Compute TRAJKOVIC keypoints 3D + TrajkovicKeypoint3D trajkovic; + trajkovic.setInputCloud (cloud); + trajkovic.setNumberOfThreads (6); + keypoints_.reset (new PointCloud); + trajkovic.compute (*keypoints_); + keypoints_indices_ = trajkovic.getKeypointsIndices (); + } + + ///////////////////////////////////////////////////////////////////////// + void + cloud_callback_2d (const CloudConstPtr& cloud) + { + FPS_CALC ("cloud callback"); + boost::mutex::scoped_lock lock (cloud_mutex_); + cloud_ = cloud; + + // Compute TRAJKOVIC keypoints 2D + TrajkovicKeypoint2D trajkovic; + trajkovic.setInputCloud (cloud); + trajkovic.setNumberOfThreads (6); + keypoints_.reset (new PointCloud); + trajkovic.compute (*keypoints_); + keypoints_indices_ = trajkovic.getKeypointsIndices (); + } + + ///////////////////////////////////////////////////////////////////////// + void + init () + { + boost::function cloud_cb; + if (enable_3d_) + cloud_cb = boost::bind (&TrajkovicDemo::cloud_callback_3d, this, _1); + else + cloud_cb = boost::bind (&TrajkovicDemo::cloud_callback_2d, this, _1); + + cloud_connection = grabber_.registerCallback (cloud_cb); + } + + ///////////////////////////////////////////////////////////////////////// + std::string + getStrBool (bool state) + { + std::ostringstream ss; + ss << state; + return (ss.str ()); + } + + ///////////////////////////////////////////////////////////////////////// + void + run () + { + grabber_.start (); + + bool image_init = false, cloud_init = false; + bool keypts = true; + + while (!cloud_viewer_.wasStopped () && !image_viewer_.wasStopped ()) + { + PointCloud::Ptr keypoints; + CloudConstPtr cloud; + if (cloud_mutex_.try_lock ()) + { + cloud_.swap (cloud); + keypoints_.swap (keypoints); + + cloud_mutex_.unlock (); + } + + if (cloud) + { + int w (cloud->width); + if (!cloud_init) + { + cloud_viewer_.setPosition (0, 0); + cloud_viewer_.setSize (cloud->width, cloud->height); + cloud_init = !cloud_init; + } + + if (!cloud_viewer_.updatePointCloud (cloud, "OpenNICloud")) + { + cloud_viewer_.addPointCloud (cloud, "OpenNICloud"); + cloud_viewer_.resetCameraViewpoint ("OpenNICloud"); + } + + if (!image_init) + { + image_viewer_.setPosition (cloud->width, 0); + image_viewer_.setSize (cloud->width, cloud->height); + image_init = !image_init; + } + + image_viewer_.addRGBImage (cloud); + + if (keypoints && !keypoints->empty ()) + { + image_viewer_.removeLayer (getStrBool (keypts)); + std::vector uv; + uv.reserve (keypoints_indices_->indices.size () * 2); + for (std::vector::const_iterator id = keypoints_indices_->indices.begin (); + id != keypoints_indices_->indices.end (); + ++id) + { + int u (*id % w); + int v (*id / w); + image_viewer_.markPoint (u, v, visualization::red_color, visualization::blue_color, 5, getStrBool (!keypts), 0.5); + } + keypts = !keypts; + + visualization::PointCloudColorHandlerCustom blue (keypoints, 0, 0, 255); + if (!cloud_viewer_.updatePointCloud (keypoints, blue, "keypoints")) + cloud_viewer_.addPointCloud (keypoints, blue, "keypoints"); + cloud_viewer_.setPointCloudRenderingProperties (visualization::PCL_VISUALIZER_POINT_SIZE, 10, "keypoints"); + cloud_viewer_.setPointCloudRenderingProperties (visualization::PCL_VISUALIZER_OPACITY, 0.5, "keypoints"); + } + } + + cloud_viewer_.spinOnce (); + image_viewer_.spinOnce (); + boost::this_thread::sleep (boost::posix_time::microseconds (100)); + } + + grabber_.stop (); + cloud_connection.disconnect (); + } + + visualization::PCLVisualizer cloud_viewer_; + Grabber& grabber_; + boost::mutex cloud_mutex_; + CloudConstPtr cloud_; + + visualization::ImageViewer image_viewer_; + + PointCloud::Ptr keypoints_; + pcl::PointIndicesConstPtr keypoints_indices_; + bool enable_3d_; + private: + boost::signals2::connection cloud_connection; +}; + +/* ---[ */ +int +main (int argc, char** argv) +{ + if (pcl::console::find_switch (argc, argv, "-h")) + { + pcl::console::print_info ("Syntax is: %s [-device device_id_string] [-2d]\n", argv[0]); + return (0); + } + + std::string device_id ("#1"); + bool enable_3d = true; + if (pcl::console::find_switch (argc, argv, "-2d")) + enable_3d = false; + + if (pcl::console::find_argument (argc, argv, "-device")) + pcl::console::parse (argc, argv, "-device", device_id); + + pcl::console::print_info ("Extracting Trajkovic %s keypoints from device %s.\n", + enable_3d ? "3D" : "2D", device_id.c_str ()); + + OpenNIGrabber grabber (device_id); + + TrajkovicDemo openni_viewer (grabber, enable_3d); + + openni_viewer.init (); + openni_viewer.run (); + + return (0); +} +/* ]--- */ diff --git a/apps/src/openni_klt.cpp b/apps/src/openni_klt.cpp new file mode 100644 index 00000000..2f1a9f00 --- /dev/null +++ b/apps/src/openni_klt.cpp @@ -0,0 +1,408 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2014-, Open Perception, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define MEASURE_FUNCTION_TIME +#include //fps calculations +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHOW_FPS 1 +#if SHOW_FPS +#define FPS_CALC(_WHAT_) \ +do \ +{ \ + static unsigned count = 0;\ + static double last = pcl::getTime ();\ + double now = pcl::getTime (); \ + ++count; \ + if (now - last >= 1.0) \ + { \ + std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(now - last) << " Hz" << std::endl; \ + count = 0; \ + last = now; \ + } \ +}while(false) +#else +#define FPS_CALC(_WHAT_) \ +do \ +{ \ +}while(false) +#endif + +void +printHelp (int, char **argv) +{ + using pcl::console::print_error; + using pcl::console::print_info; + + print_error ("Syntax is: %s [(( | ) [-depthmode ] [-imagemode ] [-xyz] | -l []| -h | --help)]\n", argv [0]); + print_info ("%s -h | --help : shows this help\n", argv [0]); + print_info ("%s -xyz : use only XYZ values and ignore RGB components (this flag is required for use with ASUS Xtion Pro) \n", argv [0]); + print_info ("%s -l : list all available devices\n", argv [0]); + print_info ("%s -l :list all available modes for specified device\n", argv [0]); + print_info ("\t\t may be \"#1\", \"#2\", ... for the first, second etc device in the list\n"); +#ifndef _WIN32 + print_info ("\t\t bus@address for the device connected to a specific usb-bus / address combination\n"); + print_info ("\t\t \n"); +#endif + print_info ("\n\nexamples:\n"); + print_info ("%s \"#1\"\n", argv [0]); + print_info ("\t\t uses the first device.\n"); + print_info ("%s \"./temp/test.oni\"\n", argv [0]); + print_info ("\t\t uses the oni-player device to play back oni file given by path.\n"); + print_info ("%s -l\n", argv [0]); + print_info ("\t\t list all available devices.\n"); + print_info ("%s -l \"#2\"\n", argv [0]); + print_info ("\t\t list all available modes for the second device.\n"); + #ifndef _WIN32 + print_info ("%s A00361800903049A\n", argv [0]); + print_info ("\t\t uses the device with the serial number \'A00361800903049A\'.\n"); + print_info ("%s 1@16\n", argv [0]); + print_info ("\t\t uses the device on address 16 at USB bus 1.\n"); + #endif +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class OpenNIViewer +{ + public: + typedef pcl::PointCloud Cloud; + typedef typename Cloud::ConstPtr CloudConstPtr; + + OpenNIViewer (pcl::Grabber& grabber) + : image_viewer_ () + , grabber_ (grabber) + , rgb_data_ (0), rgb_data_size_ (0) + { } + + void + detect_keypoints (const CloudConstPtr& cloud) + { + pcl::HarrisKeypoint2D harris; + harris.setInputCloud (cloud); + harris.setNumberOfThreads (6); + harris.setNonMaxSupression (true); + harris.setRadiusSearch (0.01); + harris.setMethod (pcl::HarrisKeypoint2D::TOMASI); + harris.setThreshold (0.05); + harris.setWindowWidth (5); + harris.setWindowHeight (5); + pcl::PointCloud::Ptr response (new pcl::PointCloud); + harris.compute (*response); + points_ = harris.getKeypointsIndices (); + } + + void + cloud_callback (const CloudConstPtr& cloud) + { + FPS_CALC ("cloud callback"); + boost::mutex::scoped_lock lock (cloud_mutex_); + cloud_ = cloud; + // Compute Tomasi keypoints + tracker_->setInputCloud (cloud_); + // if (!points_) + // { + if (!points_ || (counter_ % 10 == 0)) + { + detect_keypoints (cloud_); + tracker_->setPointsToTrack (points_); + } + + // } + tracker_->compute (); + ++counter_; + } + + void + image_callback (const boost::shared_ptr& image) + { + FPS_CALC ("image callback"); + boost::mutex::scoped_lock lock (image_mutex_); + image_ = image; + + if (image->getEncoding () != openni_wrapper::Image::RGB) + { + if (rgb_data_size_ < image->getWidth () * image->getHeight ()) + { + if (rgb_data_) + delete [] rgb_data_; + rgb_data_size_ = image->getWidth () * image->getHeight (); + rgb_data_ = new unsigned char [rgb_data_size_ * 3]; + } + image_->fillRGB (image_->getWidth (), image_->getHeight (), rgb_data_); + } + } + + void + keyboard_callback (const pcl::visualization::KeyboardEvent& event, void*) + { + static pcl::PCDWriter writer; + static std::ostringstream frame; + if (event.keyUp ()) + { + if ((event.getKeyCode () == 's') || (event.getKeyCode () == 'S')) + { + boost::mutex::scoped_lock lock (cloud_mutex_); + frame.str ("frame-"); + frame << boost::posix_time::to_iso_string (boost::posix_time::microsec_clock::local_time ()) << ".pcd"; + writer.writeBinaryCompressed (frame.str (), *cloud_); + PCL_INFO ("Written cloud %s.\n", frame.str ().c_str ()); + } + } + } + + void + mouse_callback (const pcl::visualization::MouseEvent& mouse_event, void*) + { + if (mouse_event.getType() == pcl::visualization::MouseEvent::MouseButtonPress && mouse_event.getButton() == pcl::visualization::MouseEvent::LeftButton) + { + cout << "left button pressed @ " << mouse_event.getX () << " , " << mouse_event.getY () << endl; + } + } + + /** + * @brief starts the main loop + */ + void + run () + { + boost::function cloud_cb = boost::bind (&OpenNIViewer::cloud_callback, this, _1); + boost::signals2::connection cloud_connection = grabber_.registerCallback (cloud_cb); + + boost::signals2::connection image_connection; + if (grabber_.providesCallback&)>()) + { + image_viewer_.reset (new pcl::visualization::ImageViewer ("Pyramidal KLT Tracker")); + boost::function&) > image_cb = boost::bind (&OpenNIViewer::image_callback, this, _1); + image_connection = grabber_.registerCallback (image_cb); + } + + tracker_.reset (new pcl::tracking::PyramidalKLTTracker); + + bool image_init = false; + + grabber_.start (); + + while (!image_viewer_->wasStopped ()) + { + boost::shared_ptr image; + CloudConstPtr cloud; + + // See if we can get a cloud + if (cloud_mutex_.try_lock ()) + { + cloud_.swap (cloud); + cloud_mutex_.unlock (); + } + + // See if we can get an image + if (image_mutex_.try_lock ()) + { + image_.swap (image); + image_mutex_.unlock (); + } + + if (image) + { + if (!image_init && cloud && cloud->width != 0) + { + image_viewer_->setPosition (0, 0); + image_viewer_->setSize (cloud->width, cloud->height); + image_init = !image_init; + } + + if (image->getEncoding() == openni_wrapper::Image::RGB) + image_viewer_->addRGBImage (image->getMetaData ().Data (), image->getWidth (), image->getHeight ()); + else + image_viewer_->addRGBImage (rgb_data_, image->getWidth (), image->getHeight ()); + image_viewer_->spinOnce (); + } + + if (tracker_->getInitialized () && cloud_) + { + if (points_mutex_.try_lock ()) + { + keypoints_ = tracker_->getTrackedPoints (); + points_status_ = tracker_->getPointsToTrackStatus (); + points_mutex_.unlock (); + } + + std::vector markers; + markers.reserve (keypoints_->size () * 2); + for (std::size_t i = 0; i < keypoints_->size (); ++i) + { + if (points_status_->indices[i] < 0) + continue; + const pcl::PointUV &uv = keypoints_->points[i]; + markers.push_back (uv.u); + markers.push_back (uv.v); + } + image_viewer_->removeLayer ("tracked"); + image_viewer_->markPoints (markers, pcl::visualization::blue_color, + pcl::visualization::red_color, 5, "tracked", 1.0); + + } + } + + grabber_.stop (); + + cloud_connection.disconnect (); + image_connection.disconnect (); + if (rgb_data_) + delete[] rgb_data_; + } + + boost::shared_ptr image_viewer_; + + pcl::Grabber& grabber_; + boost::mutex cloud_mutex_; + boost::mutex image_mutex_; + boost::mutex points_mutex_; + + CloudConstPtr cloud_; + boost::shared_ptr image_; + unsigned char* rgb_data_; + unsigned rgb_data_size_; + boost::shared_ptr > tracker_; + pcl::PointCloud::ConstPtr keypoints_; + pcl::PointIndicesConstPtr points_; + pcl::PointIndicesConstPtr points_status_; + int counter_; +}; + +// Create the PCLVisualizer object +boost::shared_ptr img; + +/* ---[ */ +int +main (int argc, char** argv) +{ + std::string device_id(""); + pcl::OpenNIGrabber::Mode depth_mode = pcl::OpenNIGrabber::OpenNI_Default_Mode; + pcl::OpenNIGrabber::Mode image_mode = pcl::OpenNIGrabber::OpenNI_Default_Mode; + bool xyz = false; + + if (argc >= 2) + { + device_id = argv[1]; + if (device_id == "--help" || device_id == "-h") + { + printHelp(argc, argv); + return 0; + } + else if (device_id == "-l") + { + if (argc >= 3) + { + pcl::OpenNIGrabber grabber(argv[2]); + boost::shared_ptr device = grabber.getDevice(); + cout << "Supported depth modes for device: " << device->getVendorName() << " , " << device->getProductName() << endl; + std::vector > modes = grabber.getAvailableDepthModes(); + for (std::vector >::const_iterator it = modes.begin(); it != modes.end(); ++it) + { + cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << endl; + } + + if (device->hasImageStream ()) + { + cout << endl << "Supported image modes for device: " << device->getVendorName() << " , " << device->getProductName() << endl; + modes = grabber.getAvailableImageModes(); + for (std::vector >::const_iterator it = modes.begin(); it != modes.end(); ++it) + { + cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << endl; + } + } + } + else + { + openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance(); + if (driver.getNumberDevices() > 0) + { + for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices(); ++deviceIdx) + { + cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName(deviceIdx) << ", product: " << driver.getProductName(deviceIdx) + << ", connected: " << driver.getBus(deviceIdx) << " @ " << driver.getAddress(deviceIdx) << ", serial number: \'" << driver.getSerialNumber(deviceIdx) << "\'" << endl; + } + + } + else + cout << "No devices connected." << endl; + + cout <<"Virtual Devices available: ONI player" << endl; + } + return 0; + } + } + else + { + openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance(); + if (driver.getNumberDevices() > 0) + cout << "Device Id not set, using first device." << endl; + } + + unsigned mode; + if (pcl::console::parse(argc, argv, "-depthmode", mode) != -1) + depth_mode = pcl::OpenNIGrabber::Mode (mode); + + if (pcl::console::parse(argc, argv, "-imagemode", mode) != -1) + image_mode = pcl::OpenNIGrabber::Mode (mode); + + if (pcl::console::find_argument (argc, argv, "-xyz") != -1) + xyz = true; + + pcl::OpenNIGrabber grabber (device_id, depth_mode, image_mode); + + if (xyz || !grabber.providesCallback ()) + { + OpenNIViewer openni_viewer (grabber); + openni_viewer.run (); + } + else + { + OpenNIViewer openni_viewer (grabber); + openni_viewer.run (); + } + + return (0); +} +/* ]--- */ diff --git a/apps/src/openni_organized_multi_plane_segmentation.cpp b/apps/src/openni_organized_multi_plane_segmentation.cpp index 3fbef21c..65e70496 100644 --- a/apps/src/openni_organized_multi_plane_segmentation.cpp +++ b/apps/src/openni_organized_multi_plane_segmentation.cpp @@ -73,7 +73,7 @@ class OpenNIOrganizedMultiPlaneSegmentation viewer->addPointCloud (cloud, single_color, "cloud"); viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud"); viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 0.15, "cloud"); - viewer->addCoordinateSystem (1.0); + viewer->addCoordinateSystem (1.0, "global"); viewer->initCameraParameters (); return (viewer); } @@ -95,7 +95,7 @@ class OpenNIOrganizedMultiPlaneSegmentation char name[1024]; for (size_t i = 0; i < prev_models_size; i++) { - sprintf (name, "normal_%zu", i); + sprintf (name, "normal_%lu", i); viewer->removeShape (name); sprintf (name, "plane_%02zu", i); @@ -173,7 +173,7 @@ class OpenNIOrganizedMultiPlaneSegmentation pcl::PointXYZ pt2 = pcl::PointXYZ (centroid[0] + (0.5f * model[0]), centroid[1] + (0.5f * model[1]), centroid[2] + (0.5f * model[2])); - sprintf (name, "normal_%zu", i); + sprintf (name, "normal_%lu", i); viewer->addArrow (pt2, pt1, 1.0, 0, 0, false, name); contour->points = regions[i].getContour (); diff --git a/apps/src/pcd_organized_multi_plane_segmentation.cpp b/apps/src/pcd_organized_multi_plane_segmentation.cpp index 1ae0aa9f..954a8653 100644 --- a/apps/src/pcd_organized_multi_plane_segmentation.cpp +++ b/apps/src/pcd_organized_multi_plane_segmentation.cpp @@ -68,7 +68,7 @@ class PCDOrganizedMultiPlaneSegmentation viewer.setBackgroundColor (0, 0, 0); //viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud"); //viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 0.15, "cloud"); - viewer.addCoordinateSystem (1.0); + viewer.addCoordinateSystem (1.0, "global"); viewer.initCameraParameters (); viewer.registerKeyboardCallback(&PCDOrganizedMultiPlaneSegmentation::keyboard_callback, *this, 0); } diff --git a/apps/src/pcd_select_object_plane.cpp b/apps/src/pcd_select_object_plane.cpp index 377b7030..e7c527cf 100644 --- a/apps/src/pcd_select_object_plane.cpp +++ b/apps/src/pcd_select_object_plane.cpp @@ -227,7 +227,7 @@ class ObjectSelection ec.setIndices (points_above_plane); ec.extract (euclidean_label_indices); - print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%zu", euclidean_label_indices.size ()); print_info (" clusters]\n"); + print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", euclidean_label_indices.size ()); print_info (" clusters]\n"); } // For each cluster found @@ -270,7 +270,7 @@ class ObjectSelection // Estimate normals PointCloud::Ptr normal_cloud (new PointCloud); estimateNormals (cloud_, *normal_cloud); - print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%zu", normal_cloud->size ()); print_info (" points]\n"); + print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", normal_cloud->size ()); print_info (" points]\n"); OrganizedMultiPlaneSegmentation mps; mps.setMinInliers (1000); @@ -313,7 +313,7 @@ class ObjectSelection print_highlight (stderr, "Searching for the largest plane (%2.0d) ", i++); TicToc tt; tt.tic (); seg.segment (*inliers, coefficients); - print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%zu", inliers->indices.size ()); print_info (" points]\n"); + print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", inliers->indices.size ()); print_info (" points]\n"); // No datasets could be found anymore if (inliers->indices.empty ()) @@ -335,7 +335,7 @@ class ObjectSelection cloud_segmented.swap (cloud_remaining); } } - print_highlight ("Number of planar regions detected: %zu for a cloud of %zu points\n", regions.size (), cloud_->size ()); + print_highlight ("Number of planar regions detected: %lu for a cloud of %lu points\n", regions.size (), cloud_->size ()); double max_dist = numeric_limits::max (); // Compute the distances from all the planar regions to the picked point, and select the closest region @@ -358,7 +358,7 @@ class ObjectSelection if (cloud_->isOrganized ()) { approximatePolygon (regions[idx], region, 0.01f, false, true); - print_highlight ("Planar region: %zu points initial, %zu points after refinement.\n", regions[idx].getContour ().size (), region.getContour ().size ()); + print_highlight ("Planar region: %lu points initial, %lu points after refinement.\n", regions[idx].getContour ().size (), region.getContour ().size ()); } else { @@ -384,7 +384,7 @@ class ObjectSelection PointCloud plane_hull; chull.reconstruct (plane_hull); region.setContour (plane_hull); - print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%zu", plane_hull.size ()); print_info (" points]\n"); + print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", plane_hull.size ()); print_info (" points]\n"); } } @@ -566,7 +566,7 @@ class ObjectSelection cloud_viewer_->addPointCloud (cloud_, "scene"); cloud_viewer_->resetCameraViewpoint ("scene"); - cloud_viewer_->addCoordinateSystem (0.1, 0, 0, 0); + cloud_viewer_->addCoordinateSystem (0.1, 0, 0, 0, "global"); } ///////////////////////////////////////////////////////////////////////// @@ -584,7 +584,7 @@ class ObjectSelection return (false); } print_info ("[done, "); print_value ("%g", tt.toc ()); - print_info (" ms : "); print_value ("%zu", cloud_->size ()); print_info (" points]\n"); + print_info (" ms : "); print_value ("%lu", cloud_->size ()); print_info (" points]\n"); if (cloud_->isOrganized ()) search_.reset (new search::OrganizedNeighbor); diff --git a/apps/src/render_views_tesselated_sphere.cpp b/apps/src/render_views_tesselated_sphere.cpp index 513fb526..48e7dfe8 100644 --- a/apps/src/render_views_tesselated_sphere.cpp +++ b/apps/src/render_views_tesselated_sphere.cpp @@ -61,7 +61,11 @@ pcl::apps::RenderViewsTesselatedSphere::generateViews() { vtkSmartPointer trans_filter_center = vtkSmartPointer::New (); trans_filter_center->SetTransform (trans_center); +#if VTK_MAJOR_VERSION < 6 trans_filter_center->SetInput (polydata_); +#else + trans_filter_center->SetInputData (polydata_); +#endif trans_filter_center->Update (); vtkSmartPointer mapper = vtkSmartPointer::New (); @@ -116,7 +120,6 @@ pcl::apps::RenderViewsTesselatedSphere::generateViews() { // Get camera positions vtkPolyData *sphere = subdivide->GetOutput (); - sphere->Update (); std::vector cam_positions; if (!use_vertices_) diff --git a/cmake/Modules/FindEigen.cmake b/cmake/Modules/FindEigen.cmake index 9cb7086e..5819a5c7 100644 --- a/cmake/Modules/FindEigen.cmake +++ b/cmake/Modules/FindEigen.cmake @@ -5,6 +5,7 @@ # EIGEN_FOUND - True if Eigen was found. # EIGEN_INCLUDE_DIRS - Directories containing the Eigen include files. # EIGEN_DEFINITIONS - Compiler flags for Eigen. +# EIGEN_VERSION - Package version find_package(PkgConfig QUIET) pkg_check_modules(PC_EIGEN eigen3) @@ -13,6 +14,10 @@ set(EIGEN_DEFINITIONS ${PC_EIGEN_CFLAGS_OTHER}) if(CMAKE_SYSTEM_NAME STREQUAL Linux) set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr /usr/local) endif(CMAKE_SYSTEM_NAME STREQUAL Linux) +if(APPLE) + list(APPEND CMAKE_INCLUDE_PATH /opt/local) + set(CMAKE_FIND_FRAMEWORK NEVER) +endif() find_path(EIGEN_INCLUDE_DIR Eigen/Core HINTS ${PC_EIGEN_INCLUDEDIR} ${PC_EIGEN_INCLUDE_DIRS} "${EIGEN_ROOT}" "$ENV{EIGEN_ROOT}" @@ -20,8 +25,20 @@ find_path(EIGEN_INCLUDE_DIR Eigen/Core "$ENV{PROGRAMFILES}/Eigen 3.0.0" "$ENV{PROGRAMW6432}/Eigen 3.0.0" PATH_SUFFIXES eigen3 include/eigen3 include) +if(EIGEN_INCLUDE_DIR) + file(READ "${EIGEN_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen_version_header) + + string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen_world_version_match "${_eigen_version_header}") + set(EIGEN_WORLD_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen_major_version_match "${_eigen_version_header}") + set(EIGEN_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen_minor_version_match "${_eigen_version_header}") + set(EIGEN_MINOR_VERSION "${CMAKE_MATCH_1}") + set(EIGEN_VERSION ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION}) +endif(EIGEN_INCLUDE_DIR) set(EIGEN_INCLUDE_DIRS ${EIGEN_INCLUDE_DIR}) +set(CMAKE_FIND_FRAMEWORK) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Eigen DEFAULT_MSG EIGEN_INCLUDE_DIR) @@ -29,6 +46,5 @@ find_package_handle_standard_args(Eigen DEFAULT_MSG EIGEN_INCLUDE_DIR) mark_as_advanced(EIGEN_INCLUDE_DIR) if(EIGEN_FOUND) - message(STATUS "Eigen found (include: ${EIGEN_INCLUDE_DIRS})") + message(STATUS "Eigen found (include: ${EIGEN_INCLUDE_DIRS}, version: ${EIGEN_VERSION})") endif(EIGEN_FOUND) - diff --git a/cmake/Modules/FindFZAPI.cmake b/cmake/Modules/FindFZAPI.cmake index 0cad5e0f..0f7507ae 100644 --- a/cmake/Modules/FindFZAPI.cmake +++ b/cmake/Modules/FindFZAPI.cmake @@ -6,17 +6,13 @@ # FZAPI_INCLUDE_DIRS - Directories containing the FZAPI include files. # FZAPI_LIBRARIES - Libraries needed to use FZAPI. -#MESSAGE("Searching for Fotonic in: ${FZ_API_DIR}") - if(FZ_API_DIR) # Find include dirs - #MESSAGE("Searching Fotonic includes: ${FZ_API_DIR}") find_path(FZAPI_INCLUDE_DIR fz_api.h PATHS "${FZ_API_DIR}" NO_DEFAULT_PATH DOC "Fotonic include directories") # Find libraries - #MESSAGE("Searching Fotonic libs: ${FZ_API_DIR}/Release") find_library(FZAPI_LIBS fotonic_fz_api HINTS "${FZ_API_DIR}/Release" NO_DEFAULT_PATH DOC "Fotonic libraries") @@ -24,9 +20,6 @@ else() set(FZ_API_DIR "default value" CACHE FILEPATH "directory of Fotonic API") endif() -#MESSAGE("FZAPI_INCLUDE_DIR: ${FZAPI_INCLUDE_DIR}") -#MESSAGE("FZAPI_LIBS: ${FZAPI_LIBS}") - include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FZAPI DEFAULT_MSG FZAPI_LIBS FZAPI_INCLUDE_DIR) diff --git a/cmake/Modules/FindGLEW.cmake b/cmake/Modules/FindGLEW.cmake index c45585c3..f6c6e2a1 100644 --- a/cmake/Modules/FindGLEW.cmake +++ b/cmake/Modules/FindGLEW.cmake @@ -42,11 +42,17 @@ ELSE (WIN32) IF (APPLE) # These values for Apple could probably do with improvement. + if (${CMAKE_SYSTEM_VERSION} VERSION_LESS "13.0.0") FIND_PATH( GLEW_INCLUDE_DIR glew.h /System/Library/Frameworks/GLEW.framework/Versions/A/Headers ${OPENGL_LIBRARY_DIR} - ) + ) SET(GLEW_GLEW_LIBRARY "-framework GLEW" CACHE STRING "GLEW library for OSX") + else (${CMAKE_SYSTEM_VERSION} VERSION_LESS "13.0.0") + find_package(PkgConfig) + pkg_check_modules(glew GLEW) + SET(GLEW_GLEW_LIBRARY ${GLEW_LIBRARIES} CACHE STRING "GLEW library for OSX") + endif (${CMAKE_SYSTEM_VERSION} VERSION_LESS "13.0.0") SET(GLEW_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX") ELSE (APPLE) diff --git a/cmake/Modules/FindGtest.cmake b/cmake/Modules/FindGtest.cmake new file mode 100644 index 00000000..7c393737 --- /dev/null +++ b/cmake/Modules/FindGtest.cmake @@ -0,0 +1,40 @@ +############################################################################### +# Find GTest +# +# This sets the following variables: +# GTEST_FOUND - True if GTest was found. +# GTEST_INCLUDE_DIRS - Directories containing the GTest include files. +# GTEST_SRC - Directories containing the GTest source files. + +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr /usr/local) +endif(CMAKE_SYSTEM_NAME STREQUAL Linux) +if(APPLE) + list(APPEND CMAKE_INCLUDE_PATH /opt/local) + set(CMAKE_FIND_FRAMEWORK NEVER) +endif() + +find_path(GTEST_INCLUDE_DIR gtest/gtest.h + HINTS "${GTEST_ROOT}" "$ENV{GTEST_ROOT}" + PATHS "$ENV{PROGRAMFILES}/gtest" "$ENV{PROGRAMW6432}/gtest" + PATHS "$ENV{PROGRAMFILES}/gtest-1.7.0" "$ENV{PROGRAMW6432}/gtest-1.7.0" + PATH_SUFFIXES gtest include/gtest include) + +find_path(GTEST_SRC_DIR src/gtest-all.cc + HINTS "${GTEST_ROOT}" "$ENV{GTEST_ROOT}" + PATHS "$ENV{PROGRAMFILES}/gtest" "$ENV{PROGRAMW6432}/gtest" + PATHS "$ENV{PROGRAMFILES}/gtest-1.7.0" "$ENV{PROGRAMW6432}/gtest-1.7.0" + PATH /usr/src/gtest + PATH_SUFFIXES gtest usr/src/gtest) + +set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIR}) +set(CMAKE_FIND_FRAMEWORK) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Gtest DEFAULT_MSG GTEST_INCLUDE_DIR GTEST_SRC_DIR) + +mark_as_advanced(GTEST_INCLUDE_DIR GTEST_SRC_DIR) + +if(GTEST_FOUND) + message(STATUS "GTest found (include: ${GTEST_INCLUDE_DIRS}, src: ${GTEST_SRC_DIR})") +endif(GTEST_FOUND) diff --git a/cmake/Modules/FindMPI.cmake b/cmake/Modules/FindMPI.cmake deleted file mode 100644 index bfc80eeb..00000000 --- a/cmake/Modules/FindMPI.cmake +++ /dev/null @@ -1,617 +0,0 @@ -# - Find a Message Passing Interface (MPI) implementation -# The Message Passing Interface (MPI) is a library used to write -# high-performance distributed-memory parallel applications, and -# is typically deployed on a cluster. MPI is a standard interface -# (defined by the MPI forum) for which many implementations are -# available. All of them have somewhat different include paths, -# libraries to link against, etc., and this module tries to smooth -# out those differences. -# -# === Variables === -# -# This module will set the following variables per language in your project, -# where is one of C, CXX, or Fortran: -# MPI__FOUND TRUE if FindMPI found MPI flags for -# MPI__COMPILER MPI Compiler wrapper for -# MPI__COMPILE_FLAGS Compilation flags for MPI programs -# MPI__INCLUDE_PATH Include path(s) for MPI header -# MPI__LINK_FLAGS Linking flags for MPI programs -# MPI__LIBRARIES All libraries to link MPI programs against -# Additionally, FindMPI sets the following variables for running MPI -# programs from the command line: -# MPIEXEC Executable for running MPI programs -# MPIEXEC_NUMPROC_FLAG Flag to pass to MPIEXEC before giving -# it the number of processors to run on -# MPIEXEC_PREFLAGS Flags to pass to MPIEXEC directly -# before the executable to run. -# MPIEXEC_POSTFLAGS Flags to pass to MPIEXEC after other flags -# === Usage === -# -# To use this module, simply call FindMPI from a CMakeLists.txt file, or -# run find_package(MPI), then run CMake. If you are happy with the auto- -# detected configuration for your language, then you're done. If not, you -# have two options: -# 1. Set MPI__COMPILER to the MPI wrapper (mpicc, etc.) of your -# choice and reconfigure. FindMPI will attempt to determine all the -# necessary variables using THAT compiler's compile and link flags. -# 2. If this fails, or if your MPI implementation does not come with -# a compiler wrapper, then set both MPI__LIBRARIES and -# MPI__INCLUDE_PATH. You may also set any other variables -# listed above, but these two are required. This will circumvent -# autodetection entirely. -# When configuration is successful, MPI__COMPILER will be set to the -# compiler wrapper for , if it was found. MPI__FOUND and other -# variables above will be set if any MPI implementation was found for , -# regardless of whether a compiler was found. -# -# When using MPIEXEC to execute MPI applications, you should typically use -# all of the MPIEXEC flags as follows: -# ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} PROCS -# ${MPIEXEC_PREFLAGS} EXECUTABLE ${MPIEXEC_POSTFLAGS} ARGS -# where PROCS is the number of processors on which to execute the program, -# EXECUTABLE is the MPI program, and ARGS are the arguments to pass to the -# MPI program. -# -# === Backward Compatibility === -# -# For backward compatibility with older versions of FindMPI, these -# variables are set, but deprecated: -# MPI_FOUND MPI_COMPILER MPI_LIBRARY -# MPI_COMPILE_FLAGS MPI_INCLUDE_PATH MPI_EXTRA_LIBRARY -# MPI_LINK_FLAGS MPI_LIBRARIES -# In new projects, please use the MPI__XXX equivalents. - -#============================================================================= -# Copyright 2001-2011 Kitware, Inc. -# Copyright 2010-2011 Todd Gamblin tgamblin@llnl.gov -# Copyright 2001-2009 Dave Partyka -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - -# include this to handle the QUIETLY and REQUIRED arguments -include(FindPackageHandleStandardArgs) -include(GetPrerequisites) - -# -# This part detects MPI compilers, attempting to wade through the mess of compiler names in -# a sensible way. -# -# The compilers are detected in this order: -# -# 1. Try to find the most generic availble MPI compiler, as this is usually set up by -# cluster admins. e.g., if plain old mpicc is available, we'll use it and assume it's -# the right compiler. -# -# 2. If a generic mpicc is NOT found, then we attempt to find one that matches -# CMAKE__COMPILER_ID. e.g. if you are using XL compilers, we'll try to find mpixlc -# and company, but not mpiicc. This hopefully prevents toolchain mismatches. -# -# If you want to force a particular MPI compiler other than what we autodetect (e.g. if you -# want to compile regular stuff with GNU and parallel stuff with Intel), you can always set -# your favorite MPI__COMPILER explicitly and this stuff will be ignored. -# - -# Start out with the generic MPI compiler names, as these are most commonly used. -set(_MPI_C_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r) -set(_MPI_CXX_COMPILER_NAMES mpicxx mpiCC mpcxx mpCC mpic++ mpc++ - mpicxx_r mpiCC_r mpcxx_r mpCC_r mpic++_r mpc++_r) -set(_MPI_Fortran_COMPILER_NAMES mpif95 mpif95_r mpf95 mpf95_r - mpif90 mpif90_r mpf90 mpf90_r - mpif77 mpif77_r mpf77 mpf77_r) - -# GNU compiler names -set(_MPI_GNU_C_COMPILER_NAMES mpigcc mpgcc mpigcc_r mpgcc_r) -set(_MPI_GNU_CXX_COMPILER_NAMES mpig++ mpg++ mpig++_r mpg++_r) -set(_MPI_GNU_Fortran_COMPILER_NAMES mpigfortran mpgfortran mpigfortran_r mpgfortran_r - mpig77 mpig77_r mpg77 mpg77_r) - -# Intel MPI compiler names -set(_MPI_Intel_C_COMPILER_NAMES mpiicc) -set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++ mpiiCC) -set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77) - -# PGI compiler names -set(_MPI_PGI_C_COMPILER_NAMES mpipgcc mppgcc) -set(_MPI_PGI_CXX_COMPILER_NAMES mpipgCC mppgCC) -set(_MPI_PGI_Fortran_COMPILER_NAMES mpipgf95 mpipgf90 mppgf95 mppgf90 mpipgf77 mppgf77) - -# XLC MPI Compiler names -set(_MPI_XL_C_COMPILER_NAMES mpxlc mpxlc_r mpixlc mpixlc_r) -set(_MPI_XL_CXX_COMPILER_NAMES mpixlcxx mpixlC mpixlc++ mpxlcxx mpxlc++ mpixlc++ mpxlCC - mpixlcxx_r mpixlC_r mpixlc++_r mpxlcxx_r mpxlc++_r mpixlc++_r mpxlCC_r) -set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95_r - mpixlf90 mpixlf90_r mpxlf90 mpxlf90_r - mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r - mpixlf mpixlf_r mpxlf mpxlf_r) - -# append vendor-specific compilers to the list if we either don't know the compiler id, -# or if we know it matches the regular compiler. -foreach (lang C CXX Fortran) - foreach (id GNU Intel PGI XL) - if (NOT CMAKE_${lang}_COMPILER_ID OR "${CMAKE_${lang}_COMPILER_ID}" STREQUAL "${id}") - list(APPEND _MPI_${lang}_COMPILER_NAMES ${_MPI_${id}_${lang}_COMPILER_NAMES}) - endif() - unset(_MPI_${id}_${lang}_COMPILER_NAMES) # clean up the namespace here - endforeach() -endforeach() - - -# Names to try for MPI exec -set(_MPI_EXEC_NAMES mpiexec mpirun lamexec srun) - -# Grab the path to MPI from the registry if we're on windows. -set(_MPI_PREFIX_PATH) -if(WIN32) - list(APPEND _MPI_PREFIX_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]/..") - list(APPEND _MPI_PREFIX_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH2;Path]") - list(APPEND _MPI_PREFIX_PATH "$ENV{ProgramW6432}/MPICH2/") -endif() - -# Build a list of prefixes to search for MPI. -foreach(SystemPrefixDir ${CMAKE_SYSTEM_PREFIX_PATH}) - foreach(MpiPackageDir ${_MPI_PREFIX_PATH}) - if(EXISTS ${SystemPrefixDir}/${MpiPackageDir}) - list(APPEND _MPI_PREFIX_PATH "${SystemPrefixDir}/${MpiPackageDir}") - endif() - endforeach() -endforeach() - - -# -# interrogate_mpi_compiler(lang try_libs) -# -# Attempts to extract compiler and linker args from an MPI compiler. The arguments set -# by this function are: -# -# MPI__INCLUDE_PATH MPI__LINK_FLAGS MPI__FOUND -# MPI__COMPILE_FLAGS MPI__LIBRARIES -# -# MPI__COMPILER must be set beforehand to the absolute path to an MPI compiler for -# . Additionally, MPI__INCLUDE_PATH and MPI__LIBRARIES may be set -# to skip autodetection. -# -# If try_libs is TRUE, this will also attempt to find plain MPI libraries in the usual -# way. In general, this is not as effective as interrogating the compilers, as it -# ignores language-specific flags and libraries. However, some MPI implementations -# (Windows implementations) do not have compiler wrappers, so this approach must be used. -# -function (interrogate_mpi_compiler lang try_libs) - # MPI_${lang}_NO_INTERROGATE will be set to a compiler name when the *regular* compiler was - # discovered to be the MPI compiler. This happens on machines like the Cray XE6 that use - # modules to set cc, CC, and ftn to the MPI compilers. If the user force-sets another MPI - # compiler, MPI_${lang}_COMPILER won't be equal to MPI_${lang}_NO_INTERROGATE, and we'll - # inspect that compiler anew. This allows users to set new compilers w/o rm'ing cache. - string(COMPARE NOTEQUAL "${MPI_${lang}_NO_INTERROGATE}" "${MPI_${lang}_COMPILER}" interrogate) - - # If MPI is set already in the cache, don't bother with interrogating the compiler. - if (interrogate AND ((NOT MPI_${lang}_INCLUDE_PATH) OR (NOT MPI_${lang}_LIBRARIES))) - if (MPI_${lang}_COMPILER) - # Check whether the -showme:compile option works. This indicates that we have either OpenMPI - # or a newer version of LAM-MPI, and implies that -showme:link will also work. - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -showme:compile - OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE MPI_COMPILER_RETURN) - - if (MPI_COMPILER_RETURN EQUAL 0) - # If we appear to have -showme:compile, then we should - # also have -showme:link. Try it. - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -showme:link - OUTPUT_VARIABLE MPI_LINK_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_LINK_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE MPI_COMPILER_RETURN) - - if (MPI_COMPILER_RETURN EQUAL 0) - # We probably have -showme:incdirs and -showme:libdirs as well, - # so grab that while we're at it. - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -showme:incdirs - OUTPUT_VARIABLE MPI_INCDIRS OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_INCDIRS ERROR_STRIP_TRAILING_WHITESPACE) - - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -showme:libdirs - OUTPUT_VARIABLE MPI_LIBDIRS OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_LIBDIRS ERROR_STRIP_TRAILING_WHITESPACE) - - else() - # reset things here if something went wrong. - set(MPI_COMPILE_CMDLINE) - set(MPI_LINK_CMDLINE) - endif() - endif () - - # Older versions of LAM-MPI have "-showme". Try to find that. - if (NOT MPI_COMPILER_RETURN EQUAL 0) - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -showme - OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE MPI_COMPILER_RETURN) - endif() - - # MVAPICH uses -compile-info and -link-info. Try them. - if (NOT MPI_COMPILER_RETURN EQUAL 0) - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -compile-info - OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE MPI_COMPILER_RETURN) - - # If we have compile-info, also have link-info. - if (MPI_COMPILER_RETURN EQUAL 0) - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -link-info - OUTPUT_VARIABLE MPI_LINK_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_LINK_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE MPI_COMPILER_RETURN) - endif() - - # make sure we got compile and link. Reset vars if something's wrong. - if (NOT MPI_COMPILER_RETURN EQUAL 0) - set(MPI_COMPILE_CMDLINE) - set(MPI_LINK_CMDLINE) - endif() - endif() - - # MPICH just uses "-show". Try it. - if (NOT MPI_COMPILER_RETURN EQUAL 0) - execute_process( - COMMAND ${MPI_${lang}_COMPILER} -show - OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE MPI_COMPILER_RETURN) - endif() - - if (MPI_COMPILER_RETURN EQUAL 0) - # We have our command lines, but we might need to copy MPI_COMPILE_CMDLINE - # into MPI_LINK_CMDLINE, if we didn't find the link line. - if (NOT MPI_LINK_CMDLINE) - set(MPI_LINK_CMDLINE ${MPI_COMPILE_CMDLINE}) - endif() - else() - message(STATUS "Unable to determine MPI from MPI driver ${MPI_${lang}_COMPILER}") - set(MPI_COMPILE_CMDLINE) - set(MPI_LINK_CMDLINE) - endif() - - # Here, we're done with the interrogation part, and we'll try to extract args we care - # about from what we learned from the compiler wrapper scripts. - - # If interrogation came back with something, extract our variable from the MPI command line - if (MPI_COMPILE_CMDLINE OR MPI_LINK_CMDLINE) - # Extract compile flags from the compile command line. - string(REGEX MATCHALL "(^| )-[Df]([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_FLAGS "${MPI_COMPILE_CMDLINE}") - set(MPI_COMPILE_FLAGS_WORK) - - foreach(FLAG ${MPI_ALL_COMPILE_FLAGS}) - if (MPI_COMPILE_FLAGS_WORK) - set(MPI_COMPILE_FLAGS_WORK "${MPI_COMPILE_FLAGS_WORK} ${FLAG}") - else() - set(MPI_COMPILE_FLAGS_WORK ${FLAG}) - endif() - endforeach() - - # Extract include paths from compile command line - string(REGEX MATCHALL "(^| )-I([^\" ]+|\"[^\"]+\")" MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}") - foreach(IPATH ${MPI_ALL_INCLUDE_PATHS}) - string(REGEX REPLACE "^ ?-I" "" IPATH ${IPATH}) - string(REGEX REPLACE "//" "/" IPATH ${IPATH}) - list(APPEND MPI_INCLUDE_PATH_WORK ${IPATH}) - endforeach() - - # try using showme:incdirs if extracting didn't work. - if (NOT MPI_INCLUDE_PATH_WORK) - set(MPI_INCLUDE_PATH_WORK ${MPI_INCDIRS}) - separate_arguments(MPI_INCLUDE_PATH_WORK) - endif() - - # If all else fails, just search for mpi.h in the normal include paths. - if (NOT MPI_INCLUDE_PATH_WORK) - set(MPI_HEADER_PATH "MPI_HEADER_PATH-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) - find_path(MPI_HEADER_PATH mpi.h - HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} - PATH_SUFFIXES include) - set(MPI_INCLUDE_PATH_WORK ${MPI_HEADER_PATH}) - endif() - - # Extract linker paths from the link command line - string(REGEX MATCHALL "(^| |-Wl,)-L([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_PATHS "${MPI_LINK_CMDLINE}") - set(MPI_LINK_PATH) - foreach(LPATH ${MPI_ALL_LINK_PATHS}) - string(REGEX REPLACE "^(| |-Wl,)-L" "" LPATH ${LPATH}) - string(REGEX REPLACE "//" "/" LPATH ${LPATH}) - list(APPEND MPI_LINK_PATH ${LPATH}) - endforeach() - - # try using showme:libdirs if extracting didn't work. - if (NOT MPI_LINK_PATH) - set(MPI_LINK_PATH ${MPI_LIBDIRS}) - separate_arguments(MPI_LINK_PATH) - endif() - - # Extract linker flags from the link command line - string(REGEX MATCHALL "(^| )-Wl,([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE}") - set(MPI_LINK_FLAGS_WORK) - foreach(FLAG ${MPI_ALL_LINK_FLAGS}) - if (MPI_LINK_FLAGS_WORK) - set(MPI_LINK_FLAGS_WORK "${MPI_LINK_FLAGS_WORK} ${FLAG}") - else() - set(MPI_LINK_FLAGS_WORK ${FLAG}) - endif() - endforeach() - - # Extract the set of libraries to link against from the link command - # line - string(REGEX MATCHALL "(^| )-l([^\" ]+|\"[^\"]+\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") - - # Determine full path names for all of the libraries that one needs - # to link against in an MPI program - foreach(LIB ${MPI_LIBNAMES}) - string(REGEX REPLACE "^ ?-l" "" LIB ${LIB}) - # MPI_LIB is cached by find_library, but we don't want that. Clear it first. - set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) - find_library(MPI_LIB NAMES ${LIB} HINTS ${MPI_LINK_PATH}) - - if (MPI_LIB) - list(APPEND MPI_LIBRARIES_WORK ${MPI_LIB}) - elseif (NOT MPI_FIND_QUIETLY) - message(WARNING "Unable to find MPI library ${LIB}") - endif() - endforeach() - - # Sanity check MPI_LIBRARIES to make sure there are enough libraries - list(LENGTH MPI_LIBRARIES_WORK MPI_NUMLIBS) - list(LENGTH MPI_LIBNAMES MPI_NUMLIBS_EXPECTED) - if (NOT MPI_NUMLIBS EQUAL MPI_NUMLIBS_EXPECTED) - set(MPI_LIBRARIES_WORK "MPI_${lang}_LIBRARIES-NOTFOUND") - endif() - endif() - - elseif(try_libs) - # If we didn't have an MPI compiler script to interrogate, attempt to find everything - # with plain old find functions. This is nasty because MPI implementations have LOTS of - # different library names, so this section isn't going to be very generic. We need to - # make sure it works for MS MPI, though, since there are no compiler wrappers for that. - find_path(MPI_HEADER_PATH mpi.h - HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} - PATH_SUFFIXES include Inc) - set(MPI_INCLUDE_PATH_WORK ${MPI_HEADER_PATH}) - - # Decide between 32-bit and 64-bit libraries for Microsoft's MPI - if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) - set(MS_MPI_ARCH_DIR amd64) - else() - set(MS_MPI_ARCH_DIR i386) - endif() - - set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) - find_library(MPI_LIB - NAMES mpi mpich mpich2 msmpi - HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} - PATH_SUFFIXES lib lib/${MS_MPI_ARCH_DIR} Lib Lib/${MS_MPI_ARCH_DIR}) - set(MPI_LIBRARIES_WORK ${MPI_LIB}) - - # Right now, we only know about the extra libs for C++. - # We could add Fortran here (as there is usually libfmpich, etc.), but - # this really only has to work with MS MPI on Windows. - # Assume that other MPI's are covered by the compiler wrappers. - if (${lang} STREQUAL CXX) - set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) - find_library(MPI_LIB - NAMES mpi++ mpicxx cxx mpi_cxx - HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} - PATH_SUFFIXES lib) - if (MPI_LIBRARIES_WORK AND MPI_LIB) - set(MPI_LIBRARIES_WORK "${MPI_LIBRARIES_WORK};${MPI_LIB}") - endif() - endif() - - if (NOT MPI_LIBRARIES_WORK) - set(MPI_LIBRARIES_WORK "MPI_${lang}_LIBRARIES-NOTFOUND") - endif() - endif() - - # If we found MPI, set up all of the appropriate cache entries - set(MPI_${lang}_COMPILE_FLAGS ${MPI_COMPILE_FLAGS_WORK} CACHE STRING "MPI ${lang} compilation flags" FORCE) - set(MPI_${lang}_INCLUDE_PATH ${MPI_INCLUDE_PATH_WORK} CACHE STRING "MPI ${lang} include path" FORCE) - set(MPI_${lang}_LINK_FLAGS ${MPI_LINK_FLAGS_WORK} CACHE STRING "MPI ${lang} linking flags" FORCE) - set(MPI_${lang}_LIBRARIES ${MPI_LIBRARIES_WORK} CACHE STRING "MPI ${lang} libraries to link against" FORCE) - mark_as_advanced(MPI_${lang}_COMPILE_FLAGS MPI_${lang}_INCLUDE_PATH MPI_${lang}_LINK_FLAGS MPI_${lang}_LIBRARIES) - - # clear out our temporary lib/header detectionv variable here. - set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI lib detection" FORCE) - set(MPI_HEADER_PATH "MPI_HEADER_PATH-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI header detection" FORCE) - endif() - - # finally set a found variable for each MPI language - if (MPI_${lang}_INCLUDE_PATH AND MPI_${lang}_LIBRARIES) - set(MPI_${lang}_FOUND TRUE PARENT_SCOPE) - else() - set(MPI_${lang}_FOUND FALSE PARENT_SCOPE) - endif() -endfunction() - - -# This function attempts to compile with the regular compiler, to see if MPI programs -# work with it. This is a last ditch attempt after we've tried interrogating mpicc and -# friends, and after we've tried to find generic libraries. Works on machines like -# Cray XE6, where the modules environment changes what MPI version cc, CC, and ftn use. -function(try_regular_compiler lang success) - set(scratch_directory ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) - if (${lang} STREQUAL Fortran) - set(test_file ${scratch_directory}/cmake_mpi_test.f90) - file(WRITE ${test_file} - "program hello\n" - "include 'mpif.h'\n" - "integer ierror\n" - "call MPI_INIT(ierror)\n" - "call MPI_FINALIZE(ierror)\n" - "end\n") - else() - if (${lang} STREQUAL CXX) - set(test_file ${scratch_directory}/cmake_mpi_test.cpp) - else() - set(test_file ${scratch_directory}/cmake_mpi_test.c) - endif() - file(WRITE ${test_file} - "#include \n" - "int main(int argc, char **argv) {\n" - " MPI_Init(&argc, &argv);\n" - " MPI_Finalize();\n" - "}\n") - endif() - try_compile(compiler_has_mpi ${scratch_directory} ${test_file}) - if (compiler_has_mpi) - set(MPI_${lang}_NO_INTERROGATE ${CMAKE_${lang}_COMPILER} CACHE STRING "Whether to interrogate MPI ${lang} compiler" FORCE) - set(MPI_${lang}_COMPILER ${CMAKE_${lang}_COMPILER} CACHE STRING "MPI ${lang} compiler" FORCE) - set(MPI_${lang}_COMPILE_FLAGS "" CACHE STRING "MPI ${lang} compilation flags" FORCE) - set(MPI_${lang}_INCLUDE_PATH "" CACHE STRING "MPI ${lang} include path" FORCE) - set(MPI_${lang}_LINK_FLAGS "" CACHE STRING "MPI ${lang} linking flags" FORCE) - set(MPI_${lang}_LIBRARIES "" CACHE STRING "MPI ${lang} libraries to link against" FORCE) - endif() - set(${success} ${compiler_has_mpi} PARENT_SCOPE) - unset(compiler_has_mpi CACHE) -endfunction() - -# End definitions, commence real work here. - -# Most mpi distros have some form of mpiexec which gives us something we can reliably look for. -find_program(MPIEXEC - NAMES ${_MPI_EXEC_NAMES} - PATHS ${_MPI_PREFIX_PATH} - PATH_SUFFIXES bin - DOC "Executable for running MPI programs.") - -# call get_filename_component twice to remove mpiexec and the directory it exists in (typically bin). -# This gives us a fairly reliable base directory to search for /bin /lib and /include from. -get_filename_component(_MPI_BASE_DIR "${MPIEXEC}" PATH) -get_filename_component(_MPI_BASE_DIR "${_MPI_BASE_DIR}" PATH) - -set(MPIEXEC_NUMPROC_FLAG "-np" CACHE STRING "Flag used by MPI to specify the number of processes for MPIEXEC; the next option will be the number of processes.") -set(MPIEXEC_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by MPIEXEC.") -set(MPIEXEC_POSTFLAGS "" CACHE STRING "These flags will come after all flags given to MPIEXEC.") -set(MPIEXEC_MAX_NUMPROCS "2" CACHE STRING "Maximum number of processors available to run MPI applications.") -mark_as_advanced(MPIEXEC MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS) - - -#============================================================================= -# Backward compatibility input hacks. Propagate the FindMPI hints to C and -# CXX if the respective new versions are not defined. Translate the old -# MPI_LIBRARY and MPI_EXTRA_LIBRARY to respective MPI_${lang}_LIBRARIES. -# -# Once we find the new variables, we translate them back into their old -# equivalents below. -foreach (lang C CXX) - # Old input variables. - set(_MPI_OLD_INPUT_VARS COMPILER COMPILE_FLAGS INCLUDE_PATH LINK_FLAGS) - - # Set new vars based on their old equivalents, if the new versions are not already set. - foreach (var ${_MPI_OLD_INPUT_VARS}) - if (NOT MPI_${lang}_${var} AND MPI_${var}) - set(MPI_${lang}_${var} "${MPI_${var}}") - endif() - endforeach() - - # Special handling for MPI_LIBRARY and MPI_EXTRA_LIBRARY, which we nixed in the - # new FindMPI. These need to be merged into MPI__LIBRARIES - if (NOT MPI_${lang}_LIBRARIES AND (MPI_LIBRARY OR MPI_EXTRA_LIBRARY)) - set(MPI_${lang}_LIBRARIES ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARY}) - endif() -endforeach() -#============================================================================= - - -# This loop finds the compilers and sends them off for interrogation. -foreach (lang C CXX Fortran) - if (CMAKE_${lang}_COMPILER_WORKS) - # If the user supplies a compiler *name* instead of an absolute path, assume that we need to find THAT compiler. - if (MPI_${lang}_COMPILER) - is_file_executable(MPI_${lang}_COMPILER MPI_COMPILER_IS_EXECUTABLE) - if (NOT MPI_COMPILER_IS_EXECUTABLE) - # Get rid of our default list of names and just search for the name the user wants. - set(_MPI_${lang}_COMPILER_NAMES ${MPI_${lang}_COMPILER}) - set(MPI_${lang}_COMPILER "MPI_${lang}_COMPILER-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) - # If the user specifies a compiler, we don't want to try to search libraries either. - set(try_libs FALSE) - endif() - else() - set(try_libs TRUE) - endif() - - find_program(MPI_${lang}_COMPILER - NAMES ${_MPI_${lang}_COMPILER_NAMES} - PATHS "${MPI_HOME}/bin" "$ENV{MPI_HOME}/bin" ${_MPI_PREFIX_PATH}) - interrogate_mpi_compiler(${lang} ${try_libs}) - mark_as_advanced(MPI_${lang}_COMPILER) - - # last ditch try -- if nothing works so far, just try running the regular compiler and - # see if we can create an MPI executable. - set(regular_compiler_worked 0) - if (NOT MPI_${lang}_LIBRARIES OR NOT MPI_${lang}_INCLUDE_PATH) - try_regular_compiler(${lang} regular_compiler_worked) - endif() - - if (regular_compiler_worked) - find_package_handle_standard_args(MPI_${lang} DEFAULT_MSG MPI_${lang}_COMPILER) - else() - find_package_handle_standard_args(MPI_${lang} DEFAULT_MSG MPI_${lang}_LIBRARIES MPI_${lang}_INCLUDE_PATH) - endif() - endif() -endforeach() - - -#============================================================================= -# More backward compatibility stuff -# -# Bare MPI sans ${lang} vars are set to CXX then C, depending on what was found. -# This mimics the behavior of the old language-oblivious FindMPI. -set(_MPI_OLD_VARS FOUND COMPILER INCLUDE_PATH COMPILE_FLAGS LINK_FLAGS LIBRARIES) -if (MPI_CXX_FOUND) - foreach (var ${_MPI_OLD_VARS}) - set(MPI_${var} ${MPI_CXX_${var}}) - endforeach() -elseif (MPI_C_FOUND) - foreach (var ${_MPI_OLD_VARS}) - set(MPI_${var} ${MPI_C_${var}}) - endforeach() -else() - # Note that we might still have found Fortran, but you'll need to use MPI_Fortran_FOUND - set(MPI_FOUND FALSE) -endif() - -# Chop MPI_LIBRARIES into the old-style MPI_LIBRARY and MPI_EXTRA_LIBRARY, and set them in cache. -if (MPI_LIBRARIES) - list(GET MPI_LIBRARIES 0 MPI_LIBRARY_WORK) - set(MPI_LIBRARY ${MPI_LIBRARY_WORK} CACHE FILEPATH "MPI library to link against" FORCE) -else() - set(MPI_LIBRARY "MPI_LIBRARY-NOTFOUND" CACHE FILEPATH "MPI library to link against" FORCE) -endif() - -list(LENGTH MPI_LIBRARIES MPI_NUMLIBS) -if (MPI_NUMLIBS GREATER 1) - set(MPI_EXTRA_LIBRARY_WORK ${MPI_LIBRARIES}) - list(REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0) - set(MPI_EXTRA_LIBRARY ${MPI_EXTRA_LIBRARY_WORK} CACHE STRING "Extra MPI libraries to link against" FORCE) -else() - set(MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND" CACHE STRING "Extra MPI libraries to link against" FORCE) -endif() -#============================================================================= - -# unset these vars to cleanup namespace -unset(_MPI_OLD_VARS) -unset(_MPI_PREFIX_PATH) -unset(_MPI_BASE_DIR) -foreach (lang C CXX Fortran) - unset(_MPI_${lang}_COMPILER_NAMES) -endforeach() diff --git a/cmake/Modules/FindOpenNI.cmake b/cmake/Modules/FindOpenNI.cmake index a8e6f51f..cb537be8 100644 --- a/cmake/Modules/FindOpenNI.cmake +++ b/cmake/Modules/FindOpenNI.cmake @@ -6,7 +6,7 @@ # OPENNI_INCLUDE_DIRS - Directories containing the OPENNI include files. # OPENNI_LIBRARIES - Libraries needed to use OPENNI. # OPENNI_DEFINITIONS - Compiler flags for OPENNI. -# +# # For libusb-1.0, add USB_10_ROOT if not found find_package(PkgConfig QUIET) @@ -19,21 +19,21 @@ if(NOT WIN32) PATH_SUFFIXES libusb-1.0) find_library(USB_10_LIBRARY - NAMES usb-1.0 + NAMES usb-1.0 HINTS ${PC_USB_10_LIBDIR} ${PC_USB_10_LIBRARY_DIRS} "${USB_10_ROOT}" "$ENV{USB_10_ROOT}" PATH_SUFFIXES lib) - + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(USB_10 DEFAULT_MSG USB_10_LIBRARY USB_10_INCLUDE_DIR) - + if(NOT USB_10_FOUND) - message(STATUS "OpenNI disabled because libusb-1.0 not found.") + message(STATUS "OpenNI disabled because libusb-1.0 not found.") return() else() include_directories(SYSTEM ${USB_10_INCLUDE_DIR}) endif() endif(NOT WIN32) - + if(${CMAKE_VERSION} VERSION_LESS 2.8.2) pkg_check_modules(PC_OPENNI openni-dev) else() @@ -49,11 +49,11 @@ endif(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) #add a hint so that it can find it without the pkg-config find_path(OPENNI_INCLUDE_DIR XnStatus.h - HINTS ${PC_OPENNI_INCLUDEDIR} ${PC_OPENNI_INCLUDE_DIRS} /usr/include/openni /usr/include/ni "${OPENNI_ROOT}" "$ENV{OPENNI_ROOT}" + HINTS ${PC_OPENNI_INCLUDEDIR} ${PC_OPENNI_INCLUDE_DIRS} /usr/include/openni /usr/include/ni /opt/local/include/ni "${OPENNI_ROOT}" "$ENV{OPENNI_ROOT}" PATHS "$ENV{OPEN_NI_INSTALL_PATH${OPENNI_SUFFIX}}/Include" PATH_SUFFIXES openni include Include) #add a hint so that it can find it without the pkg-config -find_library(OPENNI_LIBRARY +find_library(OPENNI_LIBRARY NAMES OpenNI${OPENNI_SUFFIX} HINTS ${PC_OPENNI_LIBDIR} ${PC_OPENNI_LIBRARY_DIRS} /usr/lib "${OPENNI_ROOT}" "$ENV{OPENNI_ROOT}" PATHS "$ENV{OPEN_NI_LIB${OPENNI_SUFFIX}}" @@ -67,12 +67,11 @@ endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OpenNI DEFAULT_MSG OPENNI_LIBRARY OPENNI_INCLUDE_DIR) - + mark_as_advanced(OPENNI_LIBRARY OPENNI_INCLUDE_DIR) -if(OPENNI_FOUND) +if(OPENNI_FOUND) # Add the include directories - set(OPENNI_INCLUDE_DIRS ${OPENNI_INCLUDE_DIR}) + set(OPENNI_INCLUDE_DIRS ${OPENNI_INCLUDE_DIR}) message(STATUS "OpenNI found (include: ${OPENNI_INCLUDE_DIRS}, lib: ${OPENNI_LIBRARY})") endif(OPENNI_FOUND) - diff --git a/cmake/Modules/FindOpenNI2.cmake b/cmake/Modules/FindOpenNI2.cmake new file mode 100644 index 00000000..036e4e04 --- /dev/null +++ b/cmake/Modules/FindOpenNI2.cmake @@ -0,0 +1,80 @@ +############################################################################### +# Find OpenNI 2 +# +# This sets the following variables: +# OPENNI2_FOUND - True if OPENNI 2 was found. +# OPENNI2_INCLUDE_DIRS - Directories containing the OPENNI 2 include files. +# OPENNI2_LIBRARIES - Libraries needed to use OPENNI 2. +# OPENNI2_DEFINITIONS - Compiler flags for OPENNI 2. +# +# For libusb-1.0, add USB_10_ROOT if not found + +find_package(PkgConfig QUIET) + +# Find LibUSB +if(NOT WIN32) + pkg_check_modules(PC_USB_10 libusb-1.0) + find_path(USB_10_INCLUDE_DIR libusb-1.0/libusb.h + HINTS ${PC_USB_10_INCLUDEDIR} ${PC_USB_10_INCLUDE_DIRS} "${USB_10_ROOT}" "$ENV{USB_10_ROOT}" + PATH_SUFFIXES libusb-1.0) + + find_library(USB_10_LIBRARY + NAMES usb-1.0 + HINTS ${PC_USB_10_LIBDIR} ${PC_USB_10_LIBRARY_DIRS} "${USB_10_ROOT}" "$ENV{USB_10_ROOT}" + PATH_SUFFIXES lib) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(USB_10 DEFAULT_MSG USB_10_LIBRARY USB_10_INCLUDE_DIR) + + if(NOT USB_10_FOUND) + message(STATUS "OpenNI 2 disabled because libusb-1.0 not found.") + return() + else() + include_directories(SYSTEM ${USB_10_INCLUDE_DIR}) + endif() +endif(NOT WIN32) + +if(${CMAKE_VERSION} VERSION_LESS 2.8.2) + pkg_check_modules(PC_OPENNI2 openni2-dev) +else() + pkg_check_modules(PC_OPENNI2 QUIET openni2-dev) +endif() + +set(OPENNI2_DEFINITIONS ${PC_OPENNI_CFLAGS_OTHER}) + +set(OPENNI2_SUFFIX) +if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + set(OPENNI2_SUFFIX 64) +endif(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + +find_path(OPENNI2_INCLUDE_DIRS OpenNI.h + PATHS + "$ENV{OPENNI2_INCLUDE${OPENNI2_SUFFIX}}" # Win64 needs '64' suffix + /usr/include/openni2 # common path for deb packages +) + +find_library(OPENNI2_LIBRARY + NAMES OpenNI2 # No suffix needed on Win64 + libOpenNI2 # Linux + PATHS "$ENV{OPENNI2_LIB${OPENNI2_SUFFIX}}" # Windows default path, Win64 needs '64' suffix + "$ENV{OPENNI2_REDIST}" # Linux install does not use a separate 'lib' directory + ) + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(OPENNI2_LIBRARIES ${OPENNI2_LIBRARY} ${LIBUSB_1_LIBRARIES}) +else() + set(OPENNI2_LIBRARIES ${OPENNI2_LIBRARY}) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OpenNI2 DEFAULT_MSG OPENNI2_LIBRARY OPENNI2_INCLUDE_DIRS) + +mark_as_advanced(OPENNI2_LIBRARY OPENNI2_INCLUDE_DIRS) + +if(OPENNI2_FOUND) + # Add the include directories + set(OPENNI2_INCLUDE_DIRS ${OPENNI2_INCLUDE_DIR}) + set(OPENNI2_REDIST_DIR $ENV{OPENNI2_REDIST${OPENNI2_SUFFIX}}) + message(STATUS "OpenNI 2 found (include: ${OPENNI2_INCLUDE_DIRS}, lib: ${OPENNI2_LIBRARY}, redist: ${OPENNI2_REDIST_DIR})") +endif(OPENNI2_FOUND) + diff --git a/cmake/Modules/FindPXCAPI.cmake b/cmake/Modules/FindPXCAPI.cmake index 3ea77f4e..be82346e 100644 --- a/cmake/Modules/FindPXCAPI.cmake +++ b/cmake/Modules/FindPXCAPI.cmake @@ -5,36 +5,29 @@ # PXCAPI_FOUND - True if PXCAPI was found. # PXCAPI_INCLUDE_DIRS - Directories containing the PXCAPI include files. # PXCAPI_LIBRARIES - Libraries needed to use PXCAPI. - -#MESSAGE("Searching for PXCAPI in: ${PXCAPI_DIR}") + +find_path(PXCAPI_DIR include/pxcimage.h + PATHS "${PXCAPI_DIR}" "C:/Program Files/Intel/PCSDK" "C:/Program Files (x86)/Intel/PCSDK" + DOC "PXCAPI include directories") if(PXCAPI_DIR) set(PXCAPI_INCLUDE_DIRS ${PXCAPI_DIR}/include ${PXCAPI_DIR}/sample/common/include) - set(PXCAPI_LIB_DIRS ${PXCAPI_DIR}/lib/x64 ${PXCAPI_DIR}/sample/common/lib/x64/v100) - set(PXCAPI_LIBS ${PXCAPI_DIR}/lib/x64/libpxc.lib ${PXCAPI_DIR}/sample/common/lib/x64/v100/libpxcutils.lib) -else() - MESSAGE("Searching PXCAPI includes: ${PXCAPI_DIR}") - find_path(PXCAPI_DIR include/pxcimage.h - PATHS "${PXCAPI_DIR}" "C:/Program Files/Intel/PCSDK" "C:/Program Files (x86)/Intel/PCSDK" - DOC "PXCAPI include directories") - if(PXCAPI_DIR) - set(PXCAPI_INCLUDE_DIRS ${PXCAPI_DIR}/include ${PXCAPI_DIR}/sample/common/include) - set(PXCAPI_LIB_DIRS ${PXCAPI_DIR}/lib/x64 ${PXCAPI_DIR}/sample/common/lib/x64/v100) - set(PXCAPI_LIBS ${PXCAPI_DIR}/lib/x64/libpxc.lib ${PXCAPI_DIR}/sample/common/lib/x64/v100/libpxcutils.lib) - else() - set(PXCAPI_DIR "directory not found (please enter)" CACHE FILEPATH "directory of PXCAPI") - endif() + find_library(PXCAPI_LIB libpxc.lib + PATHS "${PXCAPI_DIR}/lib/" NO_DEFAULT_PATH + PATH_SUFFIXES x64 Win32) + find_library(PXCAPI_SAMPLE_LIB libpxcutils.lib + PATHS "${PXCAPI_DIR}/sample/common/lib" NO_DEFAULT_PATH + PATH_SUFFIXES x64/v100 Win32/v100) + set(PXCAPI_LIBS ${PXCAPI_LIB} ${PXCAPI_SAMPLE_LIB}) endif() -MESSAGE("PXCAPI_INCLUDE_DIR: ${PXCAPI_INCLUDE_DIRS}") -MESSAGE("PXCAPI_LIBS: ${PXCAPI_LIBS}") - include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PXCAPI DEFAULT_MSG - PXCAPI_LIBS PXCAPI_INCLUDE_DIRS PXCAPI_LIB_DIRS) - + PXCAPI_LIBS PXCAPI_INCLUDE_DIRS) + +mark_as_advanced(PXCAPI_LIB PXCAPI_SAMPLE_LIB) + if(MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT") endif() - \ No newline at end of file diff --git a/cmake/Modules/FindPcap.cmake b/cmake/Modules/FindPcap.cmake index 937b6338..18e4cfa2 100644 --- a/cmake/Modules/FindPcap.cmake +++ b/cmake/Modules/FindPcap.cmake @@ -99,14 +99,9 @@ SET(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS}) SET(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES}) #Is pcap found ? -IF(PCAP_INCLUDE_DIRS AND PCAP_LIBRARIES) -SET( PCAP_FOUND "YES" ) -message(STATUS "PCAP found (include: ${PCAP_INCLUDE_DIRS}, lib: ${PCAP_LIBRARIES})") -ELSE() -SET( PCAP_FOUND "NO" ) -message(STATUS "PCAP NOT found") -ENDIF(PCAP_INCLUDE_DIRS AND PCAP_LIBRARIES) - +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PCAP DEFAULT_MSG + PCAP_LIBRARIES PCAP_INCLUDE_DIRS) MARK_AS_ADVANCED( PCAP_LIBRARIES diff --git a/cmake/Modules/FindQVTK.cmake b/cmake/Modules/FindQVTK.cmake index 18ae5767..1e9d683d 100644 --- a/cmake/Modules/FindQVTK.cmake +++ b/cmake/Modules/FindQVTK.cmake @@ -7,17 +7,26 @@ # QVTK_LIBRARY - QVTK library. # if QVTK_FOUND then QVTK_INCLUDE_DIR is appended to VTK_INCLUDE_DIRS and # QVTK_LIBRARY is appended to QVTK_LIBRARY_DIR - -find_library (QVTK_LIBRARY QVTK HINTS ${VTK_DIR} ${VTK_DIR}/bin) -find_path (QVTK_INCLUDE_DIR QVTKWidget.h HINT ${VTK_INCLUDE_DIRS}) -find_package_handle_standard_args(QVTK DEFAULT_MSG - QVTK_LIBRARY QVTK_INCLUDE_DIR) - -if(NOT QVTK_FOUND) - set (VTK_USE_QVTK OFF) -else(NOT QVTK_FOUND) - get_filename_component (QVTK_LIBRARY_DIR ${QVTK_LIBRARY} PATH) - set (VTK_LIBRARY_DIRS ${VTK_LIBRARY_DIRS} ${QVTK_LIBRARY_DIR}) - set (VTK_INCLUDE_DIRS ${VTK_INCLUDE_DIRS} ${QVTK_INCLUDE_DIR}) - set (VTK_USE_QVTK ON) -endif(NOT QVTK_FOUND) +if (${VTK_MAJOR_VERSION} VERSION_LESS "6.0") + find_library (QVTK_LIBRARY QVTK HINTS ${VTK_DIR} ${VTK_DIR}/bin) + find_path (QVTK_INCLUDE_DIR QVTKWidget.h HINT ${VTK_INCLUDE_DIRS}) + find_package_handle_standard_args(QVTK DEFAULT_MSG + QVTK_LIBRARY QVTK_INCLUDE_DIR) + if(NOT QVTK_FOUND) + set (VTK_USE_QVTK OFF) + else(NOT QVTK_FOUND) + get_filename_component (QVTK_LIBRARY_DIR ${QVTK_LIBRARY} PATH) + set (VTK_LIBRARY_DIRS ${VTK_LIBRARY_DIRS} ${QVTK_LIBRARY_DIR}) + set (VTK_INCLUDE_DIRS ${VTK_INCLUDE_DIRS} ${QVTK_INCLUDE_DIR}) + set (VTK_USE_QVTK ON) + endif(NOT QVTK_FOUND) +else (${VTK_MAJOR_VERSION} VERSION_LESS "6.0") + list (FIND VTK_MODULES_ENABLED vtkGUISupportQt GUI_SUPPORT_QT_FOUND) + list (FIND VTK_MODULES_ENABLED vtkRenderingQt RENDERING_QT_FOUND) + if (GUI_SUPPORT_QT_FOUND AND RENDERING_QT_FOUND) + set (VTK_USE_QVTK ON) + set (QVTK_LIBRARY vtkRenderingQt vtkGUISupportQt) + else (GUI_SUPPORT_QT_FOUND AND RENDERING_QT_FOUND) + unset(QVTK_FOUND) + endif (GUI_SUPPORT_QT_FOUND AND RENDERING_QT_FOUND) +endif (${VTK_MAJOR_VERSION} VERSION_LESS "6.0") diff --git a/cmake/Modules/FindQhull.cmake b/cmake/Modules/FindQhull.cmake index f5fd269d..698bd151 100644 --- a/cmake/Modules/FindQhull.cmake +++ b/cmake/Modules/FindQhull.cmake @@ -15,8 +15,8 @@ if(QHULL_USE_STATIC) set(QHULL_RELEASE_NAME qhullstatic) set(QHULL_DEBUG_NAME qhullstatic_d) else(QHULL_USE_STATIC) - set(QHULL_RELEASE_NAME qhull qhull${QHULL_MAJOR_VERSION}) - set(QHULL_DEBUG_NAME qhull_d qhull${QHULL_MAJOR_VERSION}_d qhull_d${QHULL_MAJOR_VERSION}) + set(QHULL_RELEASE_NAME qhull_p qhull${QHULL_MAJOR_VERSION} qhull) + set(QHULL_DEBUG_NAME qhull_pd qhull${QHULL_MAJOR_VERSION}_d qhull_d${QHULL_MAJOR_VERSION} qhull_d) endif(QHULL_USE_STATIC) find_file(QHULL_HEADER @@ -49,6 +49,8 @@ find_library(QHULL_LIBRARY PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull" PATH_SUFFIXES project build bin lib) +get_filename_component(QHULL_LIBRARY_NAME "${QHULL_LIBRARY}" NAME) + find_library(QHULL_LIBRARY_DEBUG NAMES ${QHULL_DEBUG_NAME} ${QHULL_RELEASE_NAME} HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" @@ -59,6 +61,8 @@ if(NOT QHULL_LIBRARY_DEBUG) set(QHULL_LIBRARY_DEBUG ${QHULL_LIBRARY}) endif(NOT QHULL_LIBRARY_DEBUG) +get_filename_component(QHULL_LIBRARY_DEBUG_NAME "${QHULL_LIBRARY_DEBUG}" NAME) + set(QHULL_INCLUDE_DIRS ${QHULL_INCLUDE_DIR}) set(QHULL_LIBRARIES optimized ${QHULL_LIBRARY} debug ${QHULL_LIBRARY_DEBUG}) diff --git a/cmake/pcl_find_boost.cmake b/cmake/pcl_find_boost.cmake index 212d2e0e..55fc40e9 100644 --- a/cmake/pcl_find_boost.cmake +++ b/cmake/pcl_find_boost.cmake @@ -1,9 +1,17 @@ # Find and set Boost flags -if(NOT PCL_SHARED_LIBS OR WIN32) - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_STATIC ON) -endif(NOT PCL_SHARED_LIBS OR WIN32) +# If we would like to compile against a dynamically linked Boost +if(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32 AND WIN32) + set(Boost_USE_STATIC_LIBS OFF) + set(Boost_USE_STATIC OFF) + set(Boost_USE_MULTITHREAD ON) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB") +else(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32 AND WIN32) + if(NOT PCL_SHARED_LIBS OR WIN32) + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_STATIC ON) + endif(NOT PCL_SHARED_LIBS OR WIN32) +endif(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32 AND WIN32) if(${CMAKE_VERSION} VERSION_LESS 2.8.5) SET(Boost_ADDITIONAL_VERSIONS "1.43" "1.43.0" "1.44" "1.44.0" "1.45" "1.45.0" "1.46.1" "1.46.0" "1.46" "1.47" "1.47.0") @@ -15,24 +23,15 @@ endif(${CMAKE_VERSION} VERSION_LESS 2.8.5) set(Boost_NO_BOOST_CMAKE ON) # Optional boost modules -find_package(Boost 1.40.0 QUIET COMPONENTS serialization mpi) -if(Boost_MPI_FOUND) - set(BOOST_MPI_FOUND TRUE) -endif(Boost_MPI_FOUND) +find_package(Boost 1.47.0 QUIET COMPONENTS serialization mpi) if(Boost_SERIALIZATION_FOUND) set(BOOST_SERIALIZATION_FOUND TRUE) endif(Boost_SERIALIZATION_FOUND) # Required boost modules -set(BOOST_REQUIRED_MODULES system filesystem thread date_time iostreams) -# Starting with Boost 1.50, boost_thread depends on chrono. As this is not -# taken care of automatically on Windows, we add an explicit dependency as a -# workaround. -if(WIN32 AND Boost_VERSION VERSION_GREATER "104900") - set(BOOST_REQUIRED_MODULES ${BOOST_REQUIRED_MODULES} chrono) -endif(WIN32 AND Boost_VERSION VERSION_GREATER "104900") +set(BOOST_REQUIRED_MODULES system filesystem thread date_time iostreams chrono) -find_package(Boost 1.40.0 REQUIRED COMPONENTS ${BOOST_REQUIRED_MODULES}) +find_package(Boost 1.47.0 REQUIRED COMPONENTS ${BOOST_REQUIRED_MODULES}) if(Boost_FOUND) set(BOOST_FOUND TRUE) diff --git a/cmake/pcl_find_gl.cmake b/cmake/pcl_find_gl.cmake new file mode 100644 index 00000000..d34f26f1 --- /dev/null +++ b/cmake/pcl_find_gl.cmake @@ -0,0 +1,20 @@ +# Try to Find OpenGL and GLUT silently +# In addition sets two flags if the found versions are Apple frameworks +# OPENGL_IS_A_FRAMEWORK +# GLUT_IS_A_FRAMEWORK + +find_package(OpenGL QUIET REQUIRED) + +if(APPLE AND OPENGL_FOUND) + if ("${OPENGL_INCLUDE_DIR}" MATCHES "\\.framework") + set(OPENGL_IS_A_FRAMEWORK TRUE) + endif ("${OPENGL_INCLUDE_DIR}" MATCHES "\\.framework") +endif(APPLE AND OPENGL_FOUND) + +find_package(GLUT QUIET) + +if(APPLE AND GLUT_FOUND) + if ("${GLUT_INCLUDE_DIR}" MATCHES "\\.framework") + set(GLUT_IS_A_FRAMEWORK TRUE) + endif ("${GLUT_INCLUDE_DIR}" MATCHES "\\.framework") +endif(APPLE AND GLUT_FOUND) diff --git a/cmake/pcl_options.cmake b/cmake/pcl_options.cmake index cedf920c..641e8c3a 100644 --- a/cmake/pcl_options.cmake +++ b/cmake/pcl_options.cmake @@ -18,6 +18,10 @@ else(PCL_SHARED_LIBS) endif(PCL_SHARED_LIBS) mark_as_advanced(PCL_SHARED_LIBS) +# Build with dynamic linking for Boost (advanced users) +option(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32 "Build against a dynamically linked Boost on Win32 platforms." OFF) +mark_as_advanced(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32) + # Precompile for a minimal set of point types instead of all. option(PCL_ONLY_CORE_POINT_TYPES "Compile explicitly only for a small subset of point types (e.g., pcl::PointXYZ instead of PCL_XYZ_POINT_TYPES)." OFF) mark_as_advanced(PCL_ONLY_CORE_POINT_TYPES) @@ -38,3 +42,13 @@ mark_as_advanced(CMAKE_TIMING_VERBOSE) option(CMAKE_MSVC_CODE_LINK_OPTIMIZATION "Enable the /GL and /LTCG code and link optimization options for MSVC. Enabled by default." ON) mark_as_advanced(CMAKE_MSVC_CODE_LINK_OPTIMIZATION) +# Project folders +option(USE_PROJECT_FOLDERS "Use folders to organize PCL projects in an IDE." OFF) +mark_as_advanced(USE_PROJECT_FOLDERS) +if(USE_PROJECT_FOLDERS) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif(USE_PROJECT_FOLDERS) + +option(BUILD_tools "Useful PCL-based command line tools" ON) + +option(WITH_DOCS "Build doxygen documentation" OFF) diff --git a/cmake/pcl_pclconfig.cmake b/cmake/pcl_pclconfig.cmake index cf16693e..b0ea48ee 100644 --- a/cmake/pcl_pclconfig.cmake +++ b/cmake/pcl_pclconfig.cmake @@ -36,14 +36,32 @@ foreach(_ss ${PCL_SUBSYSTEMS_MODULES}) endforeach(_opt_dep) set(PCLCONFIG_OPTIONAL_DEPENDENCIES "${PCLCONFIG_OPTIONAL_DEPENDENCIES})\n") endif(_opt_deps) + + #look for subsystems + string(TOUPPER "PCL_${_ss}_SUBSYS" PCL_SUBSYS_SUBSYS) + if (${PCL_SUBSYS_SUBSYS}) + string(TOUPPER "PCL_${_ss}_SUBSYS_STATUS" PCL_SUBSYS_SUBSYS_STATUS) + foreach(_sub ${${PCL_SUBSYS_SUBSYS}}) + PCL_GET_SUBSUBSYS_STATUS(_sub_status ${_ss} ${_sub}) + if (_sub_status) + set(PCLCONFIG_AVAILABLE_COMPONENTS "${PCLCONFIG_AVAILABLE_COMPONENTS} ${_sub}") + set(PCLCONFIG_AVAILABLE_COMPONENTS_LIST "${PCLCONFIG_AVAILABLE_COMPONENTS_LIST}\n# - ${_sub}") + GET_IN_MAP(_deps PCL_SUBSYS_DEPS ${_ss}_${sub}) + if(_deps) + set(PCLCONFIG_INTERNAL_DEPENDENCIES "${PCLCONFIG_INTERNAL_DEPENDENCIES}set(pcl_${_sub}_int_dep ") + foreach(_dep ${_deps}) + set(PCLCONFIG_INTERNAL_DEPENDENCIES "${PCLCONFIG_INTERNAL_DEPENDENCIES}${_dep} ") + endforeach(_dep) + set(PCLCONFIG_INTERNAL_DEPENDENCIES "${PCLCONFIG_INTERNAL_DEPENDENCIES})\n") + endif(_deps) + endif (_sub_status) + endforeach(_sub) + endif (${PCL_SUBSYS_SUBSYS}) endif(_status) endforeach(_ss) #Boost modules set(PCLCONFIG_AVAILABLE_BOOST_MODULES "system filesystem thread date_time iostreams") -if(Boost_MPI_FOUND) - set(PCLCONFIG_AVAILABLE_BOOST_MODULES "${PCLCONFIG_AVAILABLE_BOOST_MODULES} mpi") -endif(Boost_MPI_FOUND) if(Boost_SERIALIZATION_FOUND) set(PCLCONFIG_AVAILABLE_BOOST_MODULES "${PCLCONFIG_AVAILABLE_BOOST_MODULES} serialization") endif(Boost_SERIALIZATION_FOUND) diff --git a/cmake/pcl_targets.cmake b/cmake/pcl_targets.cmake index 08b1896a..79f6bed6 100644 --- a/cmake/pcl_targets.cmake +++ b/cmake/pcl_targets.cmake @@ -12,7 +12,7 @@ macro(PCL_SUBSYS_OPTION _var _name _desc _default) PCL_GET_SUBSYS_HYPERSTATUS(subsys_status ${_name}) if(NOT ("${subsys_status}" STREQUAL "AUTO_OFF")) option(${_opt_name} ${_desc} ${_default}) - if(NOT ${_default} AND NOT ${_opt_name}) + if((NOT ${_default} AND NOT ${_opt_name}) OR ("${_default}" STREQUAL "AUTO_OFF")) set(${_var} FALSE) if(${ARGC} GREATER 4) set(_reason ${ARGV4}) @@ -29,11 +29,48 @@ macro(PCL_SUBSYS_OPTION _var _name _desc _default) set(${_var} TRUE) PCL_SET_SUBSYS_STATUS(${_name} TRUE) PCL_ENABLE_DEPENDIES(${_name}) - endif(NOT ${_default} AND NOT ${_opt_name}) + endif((NOT ${_default} AND NOT ${_opt_name}) OR ("${_default}" STREQUAL "AUTO_OFF")) endif(NOT ("${subsys_status}" STREQUAL "AUTO_OFF")) PCL_ADD_SUBSYSTEM(${_name} ${_desc}) endmacro(PCL_SUBSYS_OPTION) +############################################################################### +# Add an option to build a subsystem or not. +# _var The name of the variable to store the option in. +# _parent The name of the parent subsystem +# _name The name of the option's target subsubsystem. +# _desc The description of the subsubsystem. +# _default The default value (TRUE or FALSE) +# ARGV5 The reason for disabling if the default is FALSE. +macro(PCL_SUBSUBSYS_OPTION _var _parent _name _desc _default) + set(_opt_name "BUILD_${_parent}_${_name}") + PCL_GET_SUBSYS_HYPERSTATUS(parent_status ${_parent}) + if(NOT ("${parent_status}" STREQUAL "AUTO_OFF") AND NOT ("${parent_status}" STREQUAL "OFF")) + PCL_GET_SUBSYS_HYPERSTATUS(subsys_status ${_parent}_${_name}) + if(NOT ("${subsys_status}" STREQUAL "AUTO_OFF")) + option(${_opt_name} ${_desc} ${_default}) + if((NOT ${_default} AND NOT ${_opt_name}) OR ("${_default}" STREQUAL "AUTO_OFF")) + set(${_var} FALSE) + if(${ARGC} GREATER 5) + set(_reason ${ARGV5}) + else(${ARGC} GREATER 5) + set(_reason "Disabled by default.") + endif(${ARGC} GREATER 5) + PCL_SET_SUBSYS_STATUS(${_parent}_${_name} FALSE ${_reason}) + PCL_DISABLE_DEPENDIES(${_parent}_${_name}) + elseif(NOT ${_opt_name}) + set(${_var} FALSE) + PCL_SET_SUBSYS_STATUS(${_parent}_${_name} FALSE "Disabled manually.") + PCL_DISABLE_DEPENDIES(${_parent}_${_name}) + else(NOT ${_default} AND NOT ${_opt_name}) + set(${_var} TRUE) + PCL_SET_SUBSYS_STATUS(${_parent}_${_name} TRUE) + PCL_ENABLE_DEPENDIES(${_parent}_${_name}) + endif((NOT ${_default} AND NOT ${_opt_name}) OR ("${_default}" STREQUAL "AUTO_OFF")) + endif(NOT ("${subsys_status}" STREQUAL "AUTO_OFF")) + endif(NOT ("${parent_status}" STREQUAL "AUTO_OFF") AND NOT ("${parent_status}" STREQUAL "OFF")) + PCL_ADD_SUBSUBSYSTEM(${_parent} ${_name} ${_desc}) +endmacro(PCL_SUBSUBSYS_OPTION) ############################################################################### # Make one subsystem depend on one or more other subsystems, and disable it if @@ -82,6 +119,54 @@ macro(PCL_SUBSYS_DEPEND _var _name) endif(${_var} AND (NOT ("${subsys_status}" STREQUAL "AUTO_OFF"))) endmacro(PCL_SUBSYS_DEPEND) +############################################################################### +# Make one subsystem depend on one or more other subsystems, and disable it if +# they are not being built. +# _var The cumulative build variable. This will be set to FALSE if the +# dependencies are not met. +# _parent The parent subsystem name. +# _name The name of the subsubsystem. +# ARGN The subsystems and external libraries to depend on. +macro(PCL_SUBSUBSYS_DEPEND _var _parent _name) + set(options) + set(parentArg) + set(nameArg) + set(multiValueArgs DEPS EXT_DEPS OPT_DEPS) + cmake_parse_arguments(SUBSYS "${options}" "${parentArg}" "${nameArg}" "${multiValueArgs}" ${ARGN} ) + if(SUBSUBSYS_DEPS) + SET_IN_GLOBAL_MAP(PCL_SUBSYS_DEPS ${_parent}_${_name} "${SUBSUBSYS_DEPS}") + endif(SUBSUBSYS_DEPS) + if(SUBSUBSYS_EXT_DEPS) + SET_IN_GLOBAL_MAP(PCL_SUBSYS_EXT_DEPS ${_parent}_${_name} "${SUBSUBSYS_EXT_DEPS}") + endif(SUBSUBSYS_EXT_DEPS) + if(SUBSUBSYS_OPT_DEPS) + SET_IN_GLOBAL_MAP(PCL_SUBSYS_OPT_DEPS ${_parent}_${_name} "${SUBSUBSYS_OPT_DEPS}") + endif(SUBSUBSYS_OPT_DEPS) + GET_IN_MAP(subsys_status PCL_SUBSYS_HYPERSTATUS ${_parent}_${_name}) + if(${_var} AND (NOT ("${subsys_status}" STREQUAL "AUTO_OFF"))) + if(SUBSUBSYS_DEPS) + foreach(_dep ${SUBSUBSYS_DEPS}) + PCL_GET_SUBSYS_STATUS(_status ${_dep}) + if(NOT _status) + set(${_var} FALSE) + PCL_SET_SUBSYS_STATUS(${_parent}_${_name} FALSE "Requires ${_dep}.") + else(NOT _status) + PCL_GET_SUBSYS_INCLUDE_DIR(_include_dir ${_dep}) + include_directories(${PROJECT_SOURCE_DIR}/${_include_dir}/include) + endif(NOT _status) + endforeach(_dep) + endif(SUBSUBSYS_DEPS) + if(SUBSUBSYS_EXT_DEPS) + foreach(_dep ${SUBSUBSYS_EXT_DEPS}) + string(TOUPPER "${_dep}_found" EXT_DEP_FOUND) + if(NOT ${EXT_DEP_FOUND} OR (NOT ("${EXT_DEP_FOUND}" STREQUAL "TRUE"))) + set(${_var} FALSE) + PCL_SET_SUBSYS_STATUS(${_parent}_${_name} FALSE "Requires external library ${_dep}.") + endif(NOT ${EXT_DEP_FOUND} OR (NOT ("${EXT_DEP_FOUND}" STREQUAL "TRUE"))) + endforeach(_dep) + endif(SUBSUBSYS_EXT_DEPS) + endif(${_var} AND (NOT ("${subsys_status}" STREQUAL "AUTO_OFF"))) +endmacro(PCL_SUBSUBSYS_DEPEND) ############################################################################### # Add a set of include files to install. @@ -290,6 +375,8 @@ macro(PCL_ADD_TEST _name _exename) else(${CMAKE_VERSION} VERSION_LESS 2.8.4) add_test(NAME ${_name} COMMAND ${_exename} ${PCL_ADD_TEST_ARGUMENTS}) endif(${CMAKE_VERSION} VERSION_LESS 2.8.4) + + add_dependencies(tests ${_exename}) endmacro(PCL_ADD_TEST) ############################################################################### @@ -420,6 +507,15 @@ endmacro(PCL_MAKE_PKGCONFIG_HEADER_ONLY) ############################################################################### # Reset the subsystem status map. macro(PCL_RESET_MAPS) + foreach(_ss ${PCL_SUBSYSTEMS}) + string(TOUPPER "PCL_${_ss}_SUBSYS" PCL_SUBSYS_SUBSYS) + if (${PCL_SUBSYS_SUBSYS}) + string(TOUPPER "PCL_${_ss}_SUBSYS_DESC" PCL_PARENT_SUBSYS_DESC) + set(${PCL_SUBSYS_SUBSYS_DESC} "" CACHE INTERNAL "" FORCE) + set(${PCL_SUBSYS_SUBSYS} "" CACHE INTERNAL "" FORCE) + endif (${PCL_SUBSYS_SUBSYS}) + endforeach(_ss) + set(PCL_SUBSYS_HYPERSTATUS "" CACHE INTERNAL "To Build Or Not To Build, That Is The Question." FORCE) set(PCL_SUBSYS_STATUS "" CACHE INTERNAL @@ -446,6 +542,20 @@ macro(PCL_ADD_SUBSYSTEM _name _desc) SET_IN_GLOBAL_MAP(PCL_SUBSYS_DESC ${_name} ${_desc}) endmacro(PCL_ADD_SUBSYSTEM) +############################################################################### +# Register a subsubsystem. +# _name Subsystem name. +# _desc Description of the subsystem +macro(PCL_ADD_SUBSUBSYSTEM _parent _name _desc) + string(TOUPPER "PCL_${_parent}_SUBSYS" PCL_PARENT_SUBSYS) + string(TOUPPER "PCL_${_parent}_SUBSYS_DESC" PCL_PARENT_SUBSYS_DESC) + set(_temp ${${PCL_PARENT_SUBSYS}}) + list(APPEND _temp ${_name}) + set(${PCL_PARENT_SUBSYS} ${_temp} CACHE INTERNAL "Internal list of ${_parenr} subsystems" + FORCE) + set_in_global_map(${PCL_PARENT_SUBSYS_DESC} ${_name} ${_desc}) +endmacro(PCL_ADD_SUBSUBSYSTEM) + ############################################################################### # Set the status of a subsystem. @@ -462,6 +572,22 @@ macro(PCL_SET_SUBSYS_STATUS _name _status) SET_IN_GLOBAL_MAP(PCL_SUBSYS_REASONS ${_name} ${_reason}) endmacro(PCL_SET_SUBSYS_STATUS) +############################################################################### +# Set the status of a subsystem. +# _name Subsystem name. +# _status TRUE if being built, FALSE otherwise. +# ARGN[0] Reason for not building. +macro(PCL_SET_SUBSUBSYS_STATUS _parent _name _status) + if(${ARGC} EQUAL 4) + set(_reason ${ARGV2}) + else(${ARGC} EQUAL 4) + set(_reason "No reason") + endif(${ARGC} EQUAL 4) + SET_IN_GLOBAL_MAP(PCL_SUBSYS_STATUS ${_parent}_${_name} ${_status}) + SET_IN_GLOBAL_MAP(PCL_SUBSYS_REASONS ${_parent}_${_name} ${_reason}) +endmacro(PCL_SET_SUBSUBSYS_STATUS) + + ############################################################################### # Get the status of a subsystem # _var Destination variable. @@ -470,6 +596,15 @@ macro(PCL_GET_SUBSYS_STATUS _var _name) GET_IN_MAP(${_var} PCL_SUBSYS_STATUS ${_name}) endmacro(PCL_GET_SUBSYS_STATUS) +############################################################################### +# Get the status of a subsystem +# _var Destination variable. +# _name Name of the subsystem. +macro(PCL_GET_SUBSUBSYS_STATUS _var _parent _name) + GET_IN_MAP(${_var} PCL_SUBSYS_STATUS ${_parent}_${_name}) +endmacro(PCL_GET_SUBSUBSYS_STATUS) + + ############################################################################### # Set the hyperstatus of a subsystem and its dependee # _name Subsystem name. @@ -538,7 +673,33 @@ macro(PCL_WRITE_STATUS_REPORT) foreach(_ss ${PCL_SUBSYSTEMS}) PCL_GET_SUBSYS_STATUS(_status ${_ss}) if(_status) - message(STATUS " ${_ss}") + set(message_text " ${_ss}") + string(TOUPPER "PCL_${_ss}_SUBSYS" PCL_SUBSYS_SUBSYS) + if (${PCL_SUBSYS_SUBSYS}) + set(will_build) + foreach(_sub ${${PCL_SUBSYS_SUBSYS}}) + PCL_GET_SUBSYS_STATUS(_sub_status ${_ss}_${_sub}) + if (_sub_status) + set(will_build "${will_build}\n |_ ${_sub}") + endif (_sub_status) + endforeach(_sub) + if (NOT ("${will_build}" STREQUAL "")) + set(message_text "${message_text}\n building: ${will_build}") + endif (NOT ("${will_build}" STREQUAL "")) + set(wont_build) + foreach(_sub ${${PCL_SUBSYS_SUBSYS}}) + PCL_GET_SUBSYS_STATUS(_sub_status ${_ss}_${_sub}) + PCL_GET_SUBSYS_HYPERSTATUS(_sub_hyper_status ${_ss}_${sub}) + if (NOT _sub_status OR ("${_sub_hyper_status}" STREQUAL "AUTO_OFF")) + GET_IN_MAP(_reason PCL_SUBSYS_REASONS ${_ss}_${_sub}) + set(wont_build "${wont_build}\n |_ ${_sub}: ${_reason}") + endif (NOT _sub_status OR ("${_sub_hyper_status}" STREQUAL "AUTO_OFF")) + endforeach(_sub) + if (NOT ("${wont_build}" STREQUAL "")) + set(message_text "${message_text}\n not building: ${wont_build}") + endif (NOT ("${wont_build}" STREQUAL "")) + endif (${PCL_SUBSYS_SUBSYS}) + message(STATUS "${message_text}") endif(_status) endforeach(_ss) @@ -565,7 +726,7 @@ endmacro(PCL_WRITE_STATUS_REPORT) # exception_list OPTIONAL and contains list of subdirectories not to account macro(collect_subproject_directory_names dirname filename names dirs) file(GLOB globbed RELATIVE "${dirname}" "${dirname}/*/${filename}") - if(${ARGC} GREATER 3) + if(${ARGC} GREATER 4) set(exclusion_list ${ARGN}) foreach(file ${globbed}) get_filename_component(dir ${file} PATH) @@ -574,18 +735,15 @@ macro(collect_subproject_directory_names dirname filename names dirs) set(${dirs} ${${dirs}} ${dir}) endif(excluded EQUAL -1) endforeach() - else(${ARGC} GREATER 3) + else(${ARGC} GREATER 4) foreach(file ${globbed}) get_filename_component(dir ${file} PATH) set(${dirs} ${${dirs}} ${dir}) endforeach(file) - endif(${ARGC} GREATER 3) + endif(${ARGC} GREATER 4) foreach(subdir ${${dirs}}) - file(STRINGS ${dirname}/${subdir}/CMakeLists.txt name REGEX "set.*SUBSYS_NAME .*\\)$") - string(REGEX REPLACE "set.*SUBSYS_NAME" "" name "${name}") - string(REPLACE ")" "" name "${name}") - string(STRIP "${name}" name) -# message(STATUS "setting ${subdir} component name to ${name}") + file(STRINGS ${dirname}/${subdir}/CMakeLists.txt name REGEX "[setSET ]+\\(.*SUBSYS_NAME .*\\)$") + string(REGEX REPLACE "[setSET ]+\\(.*SUBSYS_NAME[ ]+([A-Za-z0-9_]+)[ ]*\\)" "\\1" name "${name}") set(${names} ${${names}} ${name}) file(STRINGS ${dirname}/${subdir}/CMakeLists.txt DEPENDENCIES REGEX "set.*SUBSYS_DEPS .*\\)") string(REGEX REPLACE "set.*SUBSYS_DEPS" "" DEPENDENCIES "${DEPENDENCIES}") diff --git a/cmake/pcl_utils.cmake b/cmake/pcl_utils.cmake index 976bb9dd..55b0820f 100644 --- a/cmake/pcl_utils.cmake +++ b/cmake/pcl_utils.cmake @@ -41,6 +41,20 @@ macro(PREFIX_LIST _output _prefix _list) endforeach(_item) endmacro(PREFIX_LIST) +############################################################################### +# Remove vtk definitions +# This is used for CUDA targets, because nvcc does not like VTK 6+ definitions +# style. +macro(REMOVE_VTK_DEFINITIONS) + get_directory_property(_dir_defs DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS) + set(_vtk_definitions) + foreach(_item ${_dir_defs}) + if(_item MATCHES "vtk*") + list(APPEND _vtk_definitions -D${_item}) + endif() + endforeach() + remove_definitions(${_vtk_definitions}) +endmacro(REMOVE_VTK_DEFINITIONS) ############################################################################### # Pull the component parts out of the version number. @@ -84,8 +98,12 @@ macro(SET_INSTALL_DIRS) if (NOT DEFINED LIB_INSTALL_DIR) set(LIB_INSTALL_DIR "lib") endif (NOT DEFINED LIB_INSTALL_DIR) - set(INCLUDE_INSTALL_ROOT - "include/${PROJECT_NAME_LOWER}-${PCL_MAJOR_VERSION}.${PCL_MINOR_VERSION}") + if(NOT ANDROID) + set(INCLUDE_INSTALL_ROOT + "include/${PROJECT_NAME_LOWER}-${PCL_MAJOR_VERSION}.${PCL_MINOR_VERSION}") + else(NOT ANDROID) + set(INCLUDE_INSTALL_ROOT "include") # Android, don't put into subdir + endif(NOT ANDROID) set(INCLUDE_INSTALL_DIR "${INCLUDE_INSTALL_ROOT}/pcl") set(DOC_INSTALL_DIR "share/doc/${PROJECT_NAME_LOWER}-${PCL_MAJOR_VERSION}.${PCL_MINOR_VERSION}") set(BIN_INSTALL_DIR "bin") diff --git a/cmake/uninstall_target.cmake.in b/cmake/uninstall_target.cmake.in index a3c4053c..d1191233 100644 --- a/cmake/uninstall_target.cmake.in +++ b/cmake/uninstall_target.cmake.in @@ -5,7 +5,6 @@ endif(NOT EXISTS "@PROJECT_BINARY_DIR@/install_manifest.txt") file(READ "@PROJECT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) - message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") if(EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}") exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" @@ -49,18 +48,19 @@ else(EXISTS "@CMAKE_INSTALL_PREFIX@/@PCLCONFIG_INSTALL_DIR@") "Directory \"@CMAKE_INSTALL_PREFIX@/@PCLCONFIG_INSTALL_DIR@\" does not exist.") endif(EXISTS "@CMAKE_INSTALL_PREFIX@/@PCLCONFIG_INSTALL_DIR@") -# remove pcl directory in share (removes all files in it!) -# created by CMakeLists.txt for PCLConfig.cmake -message(STATUS "Uninstalling \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\"") -if(EXISTS "@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@") - exec_program("@CMAKE_COMMAND@" - ARGS "-E remove_directory \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\"" - OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval) - if(NOT "${rm_retval}" STREQUAL 0) - message(FATAL_ERROR - "Problem when removing \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\"") - endif(NOT "${rm_retval}" STREQUAL 0) -else(EXISTS "@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@") - message(STATUS - "Directory \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\" does not exist.") -endif(EXISTS "@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@") +# remove pcl directory in share/doc (removes all files in it!) +if(@WITH_DOCS@) + message(STATUS "Uninstalling \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\"") + if(EXISTS "@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@") + exec_program("@CMAKE_COMMAND@" + ARGS "-E remove_directory \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\"" + OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR + "Problem when removing \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\"") + endif(NOT "${rm_retval}" STREQUAL 0) + else(EXISTS "@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@") + message(STATUS + "Directory \"@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@\" does not exist.") + endif(EXISTS "@CMAKE_INSTALL_PREFIX@/@DOC_INSTALL_DIR@") +endif() diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 54113ceb..34ac2990 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -3,13 +3,14 @@ set(SUBSYS_DESC "Point cloud common library") set(SUBSYS_DEPS) set(build TRUE) -PCL_SUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSYS_DESC} ON) -PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS eigen boost) +PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON) +PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS eigen boost) -PCL_ADD_DOC(${SUBSYS_NAME}) +PCL_ADD_DOC("${SUBSYS_NAME}") if(build) set(range_image_incs + include/pcl/range_image/bearing_angle_image.h include/pcl/range_image/range_image.h include/pcl/range_image/range_image_planar.h include/pcl/range_image/range_image_spherical.h @@ -22,6 +23,7 @@ if(build) ) set(range_image_srcs + src/bearing_angle_image.cpp src/range_image.cpp src/range_image_planar.cpp ) @@ -33,7 +35,6 @@ if(build) src/common.cpp src/correspondence.cpp src/distances.cpp - src/intersections.cpp src/parse.cpp src/poses_from_matches.cpp src/print.cpp @@ -53,7 +54,6 @@ if(build) include/pcl/point_traits.h include/pcl/point_types_conversion.h include/pcl/point_representation.h - include/pcl/correspondence.h include/pcl/point_types.h include/pcl/for_each_type.h include/pcl/pcl_tests.h @@ -90,6 +90,7 @@ if(build) include/pcl/common/common_headers.h include/pcl/common/distances.h include/pcl/common/eigen.h + include/pcl/common/copy_point.h include/pcl/common/io.h include/pcl/common/file_io.h include/pcl/common/intersections.h @@ -124,6 +125,8 @@ if(build) include/pcl/common/impl/centroid.hpp include/pcl/common/impl/common.hpp include/pcl/common/impl/eigen.hpp + include/pcl/common/impl/intersections.hpp + include/pcl/common/impl/copy_point.hpp include/pcl/common/impl/io.hpp include/pcl/common/impl/file_io.hpp include/pcl/common/impl/norms.hpp @@ -139,6 +142,7 @@ if(build) include/pcl/common/impl/random.hpp include/pcl/common/impl/generate.hpp include/pcl/common/impl/projection_matrix.hpp + include/pcl/common/impl/accumulators.hpp ) set(impl_incs @@ -168,22 +172,22 @@ if(build) src/fft/kiss_fft.c src/fft/kiss_fftr.c) - set(LIB_NAME pcl_${SUBSYS_NAME}) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - PCL_ADD_LIBRARY(${LIB_NAME} ${SUBSYS_NAME} ${srcs} ${kissfft_srcs} ${incs} ${common_incs} ${impl_incs} ${ros_incs} ${tools_incs} ${kissfft_incs} ${common_incs_impl} ${range_image_incs} ${range_image_incs_impl}) - #PCL_ADD_LIBRARY(${LIB_NAME} ${SUBSYS_NAME} ${srcs} ${incs} ${common_incs} ${impl_incs} ${ros_incs} ${tools_incs} ${common_incs_impl} ${range_image_incs} ${range_image_incs_impl}) - PCL_MAKE_PKGCONFIG(${LIB_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" "" "" + set(LIB_NAME "pcl_${SUBSYS_NAME}") + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") + PCL_ADD_LIBRARY("${LIB_NAME}" "${SUBSYS_NAME}" ${srcs} ${kissfft_srcs} ${incs} ${common_incs} ${impl_incs} ${ros_incs} ${tools_incs} ${kissfft_incs} ${common_incs_impl} ${range_image_incs} ${range_image_incs_impl}) + #PCL_ADD_LIBRARY("${LIB_NAME}" "${SUBSYS_NAME}" ${srcs} ${incs} ${common_incs} ${impl_incs} ${ros_incs} ${tools_incs} ${common_incs_impl} ${range_image_incs} ${range_image_incs_impl}) + PCL_MAKE_PKGCONFIG("${LIB_NAME}" "${SUBSYS_NAME}" "${SUBSYS_DESC}" "" "" "" "" "") # Install include files - PCL_ADD_INCLUDES(${SUBSYS_NAME} "" ${incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} common ${common_incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} common/fft ${kissfft_incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} common/impl ${common_incs_impl}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} impl ${impl_incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} ros ${ros_incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} console ${tools_incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} range_image ${range_image_incs}) - PCL_ADD_INCLUDES(${SUBSYS_NAME} range_image/impl ${range_image_incs_impl}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" "" ${incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" common ${common_incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" common/fft ${kissfft_incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" common/impl ${common_incs_impl}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" impl ${impl_incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" ros ${ros_incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" console ${tools_incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" range_image ${range_image_incs}) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" range_image/impl ${range_image_incs_impl}) endif(build) diff --git a/common/include/pcl/PCLHeader.h b/common/include/pcl/PCLHeader.h index cdccbe6b..84a64076 100644 --- a/common/include/pcl/PCLHeader.h +++ b/common/include/pcl/PCLHeader.h @@ -18,9 +18,14 @@ namespace pcl PCLHeader (): seq (0), stamp (), frame_id () {} + /** \brief Sequence number */ pcl::uint32_t seq; + /** \brief A timestamp associated with the time when the data was acquired + * + * The value represents microseconds since 1970-01-01 00:00:00 (the UNIX epoch). + */ pcl::uint64_t stamp; - + /** \brief Coordinate frame ID */ std::string frame_id; typedef boost::shared_ptr Ptr; diff --git a/common/include/pcl/common/centroid.h b/common/include/pcl/common/centroid.h index 112b9565..535ddf0c 100644 --- a/common/include/pcl/common/centroid.h +++ b/common/include/pcl/common/centroid.h @@ -58,6 +58,7 @@ namespace pcl * \param[out] centroid the output centroid * \return number of valid point used to determine the centroid. In case of dense point clouds, this is the same as the size of input cloud. * \note if return value is 0, the centroid is not changed, thus not valid. + * The last compononent of the vector is set to 1, this allow to transform the centroid vector with 4x4 matrices. * \ingroup common */ template inline unsigned int @@ -83,6 +84,7 @@ namespace pcl * \param[out] centroid the output centroid * \return number of valid point used to determine the centroid. In case of dense point clouds, this is the same as the size of input cloud. * \note if return value is 0, the centroid is not changed, thus not valid. + * The last compononent of the vector is set to 1, this allow to transform the centroid vector with 4x4 matrices. * \ingroup common */ template inline unsigned int @@ -110,6 +112,7 @@ namespace pcl * \param[out] centroid the output centroid * \return number of valid point used to determine the centroid. In case of dense point clouds, this is the same as the size of input cloud. * \note if return value is 0, the centroid is not changed, thus not valid. + * The last compononent of the vector is set to 1, this allow to transform the centroid vector with 4x4 matrices. * \ingroup common */ template inline unsigned int @@ -140,6 +143,7 @@ namespace pcl * \param[out] centroid the output centroid * \return number of valid point used to determine the centroid. In case of dense point clouds, this is the same as the size of input cloud. * \note if return value is 0, the centroid is not changed, thus not valid. + * The last compononent of the vector is set to 1, this allow to transform the centroid vector with 4x4 matrices. * \ingroup common */ template inline unsigned int @@ -945,6 +949,184 @@ namespace pcl return (computeNDCentroid (cloud, indices, centroid)); } +} + +#include + +namespace pcl +{ + + /** A generic class that computes the centroid of points fed to it. + * + * Here by "centroid" we denote not just the mean of 3D point coordinates, + * but also mean of values in the other data fields. The general-purpose + * \ref computeNDCentroid() function also implements this sort of + * functionality, however it does it in a "dumb" way, i.e. regardless of the + * semantics of the data inside a field it simply averages the values. In + * certain cases (e.g. for \c x, \c y, \c z, \c intensity fields) this + * behavior is reasonable, however in other cases (e.g. \c rgb, \c rgba, + * \c label fields) this does not lead to meaningful results. + * + * This class is capable of computing the centroid in a "smart" way, i.e. + * taking into account the meaning of the data inside fields. Currently the + * following fields are supported: + * + * - XYZ (\c x, \c y, \c z) + * + * Separate average for each field. + * + * - Normal (\c normal_x, \c normal_y, \c normal_z) + * + * Separate average for each field, and the resulting vector is normalized. + * + * - Curvature (\c curvature) + * + * Average. + * + * - RGB/RGBA (\c rgb or \c rgba) + * + * Separate average for R, G, B, and alpha channels. + * + * - Intensity (\c intensity) + * + * Average. + * + * - Label (\c label) + * + * Majority vote. If several labels have the same largest support then the + * smaller label wins. + * + * The template parameter defines the type of points that may be accumulated + * with this class. This may be an arbitrary PCL point type, and centroid + * computation will happen only for the fields that are present in it and are + * supported. + * + * Current centroid may be retrieved at any time using get(). Note that the + * function is templated on point type, so it is possible to fetch the + * centroid into a point type that differs from the type of points that are + * being accumulated. All the "extra" fields for which the centroid is not + * being calculated will be left untouched. + * + * Example usage: + * + * \code + * // Create and accumulate points + * CentroidPoint centroid; + * centroid.add (pcl::PointXYZ (1, 2, 3); + * centroid.add (pcl::PointXYZ (5, 6, 7); + * // Fetch centroid using `get()` + * pcl::PointXYZ c1; + * centroid.get (c1); + * // The expected result is: c1.x == 3, c1.y == 4, c1.z == 5 + * // It is also okay to use `get()` with a different point type + * pcl::PointXYZRGB c2; + * centroid.get (c2); + * // The expected result is: c2.x == 3, c2.y == 4, c2.z == 5, + * // and c2.rgb is left untouched + * \endcode + * + * \note Assumes that the points being inserted are valid. + * + * \note This class template can be successfully instantiated for *any* + * PCL point type. Of course, each of the field averages is computed only if + * the point type has the corresponding field. + * + * \ingroup common + * \author Sergey Alexandrov */ + template + class CentroidPoint + { + + public: + + CentroidPoint () + : num_points_ (0) + { + } + + /** Add a new point to the centroid computation. + * + * In this function only the accumulators and point counter are updated, + * actual centroid computation does not happen until get() is called. */ + void + add (const PointT& point) + { + // Invoke add point on each accumulator + boost::fusion::for_each (accumulators_, detail::AddPoint (point)); + ++num_points_; + } + + /** Retrieve the current centroid. + * + * Computation (division of accumulated values by the number of points + * and normalization where applicable) happens here. The result is not + * cached, so any subsequent call to this function will trigger + * re-computation. + * + * If the number of accumulated points is zero, then the point will be + * left untouched. */ + template void + get (PointOutT& point) const + { + if (num_points_ != 0) + { + // Filter accumulators so that only those that are compatible with + // both PointT and requested point type remain + typename pcl::detail::Accumulators::type ca (accumulators_); + // Invoke get point on each accumulator in filtered list + boost::fusion::for_each (ca, detail::GetPoint (point, num_points_)); + } + } + + /** Get the total number of points that were added. */ + size_t + getSize () const + { + return (num_points_); + } + + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + private: + + size_t num_points_; + typename pcl::detail::Accumulators::type accumulators_; + + }; + + /** Compute the centroid of a set of points and return it as a point. + * + * Implementation leverages \ref CentroidPoint class and therefore behaves + * differently from \ref compute3DCentroid() and \ref computeNDCentroid(). + * See \ref CentroidPoint documentation for explanation. + * + * \param[in] cloud input point cloud + * \param[out] centroid output centroid + * + * \return number of valid points used to determine the centroid (will be the + * same as the size of the cloud if it is dense) + * + * \note If return value is \c 0, then the centroid is not changed, thus is + * not valid. + * + * \ingroup common */ + template size_t + computeCentroid (const pcl::PointCloud& cloud, + PointOutT& centroid); + + /** Compute the centroid of a set of points and return it as a point. + * \param[in] cloud + * \param[in] indices point cloud indices that need to be used + * \param[out] centroid + * This is an overloaded function provided for convenience. See the + * documentation for computeCentroid(). + * + * \ingroup common */ + template size_t + computeCentroid (const pcl::PointCloud& cloud, + const std::vector& indices, + PointOutT& centroid); + } /*@}*/ #include diff --git a/common/include/pcl/common/copy_point.h b/common/include/pcl/common/copy_point.h new file mode 100644 index 00000000..0e80cfe7 --- /dev/null +++ b/common/include/pcl/common/copy_point.h @@ -0,0 +1,62 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2014-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PCL_COMMON_COPY_POINT_H_ +#define PCL_COMMON_COPY_POINT_H_ + +namespace pcl +{ + + /** \brief Copy the fields of a source point into a target point. + * + * If the source and the target point types are the same, then a complete + * copy is made. Otherwise only those fields that the two point types share + * in common are copied. + * + * \param[in] point_in the source point + * \param[out] point_out the target point + * + * \ingroup common */ + template void + copyPoint (const PointInT& point_in, PointOutT& point_out); + +} + +#include + +#endif // PCL_COMMON_COPY_POINT_H_ + diff --git a/common/include/pcl/common/eigen.h b/common/include/pcl/common/eigen.h index 0f030f41..9557f030 100644 --- a/common/include/pcl/common/eigen.h +++ b/common/include/pcl/common/eigen.h @@ -53,6 +53,7 @@ #endif #include +#include #include #include @@ -70,88 +71,15 @@ namespace pcl * \param[in] c constant parameter * \param[out] roots solutions of x^2 + b*x + c = 0 */ - template inline void - computeRoots2 (const Scalar& b, const Scalar& c, Roots& roots) - { - roots (0) = Scalar (0); - Scalar d = Scalar (b * b - 4.0 * c); - if (d < 0.0) // no real roots!!!! THIS SHOULD NOT HAPPEN! - d = 0.0; - - Scalar sd = ::std::sqrt (d); - - roots (2) = 0.5f * (b + sd); - roots (1) = 0.5f * (b - sd); - } + template void + computeRoots2 (const Scalar &b, const Scalar &c, Roots &roots); /** \brief computes the roots of the characteristic polynomial of the input matrix m, which are the eigenvalues * \param[in] m input matrix * \param[out] roots roots of the characteristic polynomial of the input matrix m, which are the eigenvalues */ - template inline void - computeRoots (const Matrix& m, Roots& roots) - { - typedef typename Matrix::Scalar Scalar; - - // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The - // eigenvalues are the roots to this equation, all guaranteed to be - // real-valued, because the matrix is symmetric. - Scalar c0 = m (0, 0) * m (1, 1) * m (2, 2) - + Scalar (2) * m (0, 1) * m (0, 2) * m (1, 2) - - m (0, 0) * m (1, 2) * m (1, 2) - - m (1, 1) * m (0, 2) * m (0, 2) - - m (2, 2) * m (0, 1) * m (0, 1); - Scalar c1 = m (0, 0) * m (1, 1) - - m (0, 1) * m (0, 1) + - m (0, 0) * m (2, 2) - - m (0, 2) * m (0, 2) + - m (1, 1) * m (2, 2) - - m (1, 2) * m (1, 2); - Scalar c2 = m (0, 0) + m (1, 1) + m (2, 2); - - - if (fabs (c0) < Eigen::NumTraits::epsilon ())// one root is 0 -> quadratic equation - computeRoots2 (c2, c1, roots); - else - { - const Scalar s_inv3 = Scalar (1.0 / 3.0); - const Scalar s_sqrt3 = std::sqrt (Scalar (3.0)); - // Construct the parameters used in classifying the roots of the equation - // and in solving the equation for the roots in closed form. - Scalar c2_over_3 = c2*s_inv3; - Scalar a_over_3 = (c1 - c2 * c2_over_3) * s_inv3; - if (a_over_3 > Scalar (0)) - a_over_3 = Scalar (0); - - Scalar half_b = Scalar (0.5) * (c0 + c2_over_3 * (Scalar (2) * c2_over_3 * c2_over_3 - c1)); - - Scalar q = half_b * half_b + a_over_3 * a_over_3*a_over_3; - if (q > Scalar (0)) - q = Scalar (0); - - // Compute the eigenvalues by solving for the roots of the polynomial. - Scalar rho = std::sqrt (-a_over_3); - Scalar theta = std::atan2 (std::sqrt (-q), half_b) * s_inv3; - Scalar cos_theta = std::cos (theta); - Scalar sin_theta = std::sin (theta); - roots (0) = c2_over_3 + Scalar (2) * rho * cos_theta; - roots (1) = c2_over_3 - rho * (cos_theta + s_sqrt3 * sin_theta); - roots (2) = c2_over_3 - rho * (cos_theta - s_sqrt3 * sin_theta); - - // Sort in increasing order. - if (roots (0) >= roots (1)) - std::swap (roots (0), roots (1)); - if (roots (1) >= roots (2)) - { - std::swap (roots (1), roots (2)); - if (roots (0) >= roots (1)) - std::swap (roots (0), roots (1)); - } - - if (roots (0) <= 0) // eigenval for symetric positive semi-definite matrix can not be negative! Set it to 0 - computeRoots2 (c2, c1, roots); - } - } + template void + computeRoots (const Matrix &m, Roots &roots); /** \brief determine the smallest eigenvalue and its corresponding eigenvector * \param[in] mat input matrix that needs to be symmetric and positive semi definite @@ -159,43 +87,8 @@ namespace pcl * \param[out] eigenvector the corresponding eigenvector to the smallest eigenvalue of the input matrix * \ingroup common */ - template inline void - eigen22 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenvector) - { - // if diagonal matrix, the eigenvalues are the diagonal elements - // and the eigenvectors are not unique, thus set to Identity - if (fabs(mat.coeff (1)) <= std::numeric_limits::min ()) - { - if (mat.coeff (0) < mat.coeff (2)) - { - eigenvalue = mat.coeff (0); - eigenvector [0] = 1.0; - eigenvector [1] = 0.0; - } - else - { - eigenvalue = mat.coeff (2); - eigenvector [0] = 0.0; - eigenvector [1] = 1.0; - } - return; - } - - // 0.5 to optimize further calculations - typename Matrix::Scalar trace = static_cast (0.5) * (mat.coeff (0) + mat.coeff (3)); - typename Matrix::Scalar determinant = mat.coeff (0) * mat.coeff (3) - mat.coeff (1) * mat.coeff (1); - - typename Matrix::Scalar temp = trace * trace - determinant; - - if (temp < 0) - temp = 0; - - eigenvalue = trace - ::std::sqrt (temp); - - eigenvector [0] = - mat.coeff (1); - eigenvector [1] = mat.coeff (0) - eigenvalue; - eigenvector.normalize (); - } + template void + eigen22 (const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector); /** \brief determine the smallest eigenvalue and its corresponding eigenvector * \param[in] mat input matrix that needs to be symmetric and positive semi definite @@ -203,58 +96,8 @@ namespace pcl * \param[out] eigenvalues the smallest eigenvalue of the input matrix * \ingroup common */ - template inline void - eigen22 (const Matrix& mat, Matrix& eigenvectors, Vector& eigenvalues) - { - // if diagonal matrix, the eigenvalues are the diagonal elements - // and the eigenvectors are not unique, thus set to Identity - if (fabs(mat.coeff (1)) <= std::numeric_limits::min ()) - { - if (mat.coeff (0) < mat.coeff (3)) - { - eigenvalues.coeffRef (0) = mat.coeff (0); - eigenvalues.coeffRef (1) = mat.coeff (3); - eigenvectors.coeffRef (0) = 1.0; - eigenvectors.coeffRef (1) = 0.0; - eigenvectors.coeffRef (2) = 0.0; - eigenvectors.coeffRef (3) = 1.0; - } - else - { - eigenvalues.coeffRef (0) = mat.coeff (3); - eigenvalues.coeffRef (1) = mat.coeff (0); - eigenvectors.coeffRef (0) = 0.0; - eigenvectors.coeffRef (1) = 1.0; - eigenvectors.coeffRef (2) = 1.0; - eigenvectors.coeffRef (3) = 0.0; - } - return; - } - - // 0.5 to optimize further calculations - typename Matrix::Scalar trace = static_cast (0.5) * (mat.coeff (0) + mat.coeff (3)); - typename Matrix::Scalar determinant = mat.coeff (0) * mat.coeff (3) - mat.coeff (1) * mat.coeff (1); - - typename Matrix::Scalar temp = trace * trace - determinant; - - if (temp < 0) - temp = 0; - else - temp = ::std::sqrt (temp); - - eigenvalues.coeffRef (0) = trace - temp; - eigenvalues.coeffRef (1) = trace + temp; - - // either this is in a row or column depending on RowMajor or ColumnMajor - eigenvectors.coeffRef (0) = - mat.coeff (1); - eigenvectors.coeffRef (2) = mat.coeff (0) - eigenvalues.coeff (0); - typename Matrix::Scalar norm = static_cast (1.0) / - static_cast (::std::sqrt (eigenvectors.coeffRef (0) * eigenvectors.coeffRef (0) + eigenvectors.coeffRef (2) * eigenvectors.coeffRef (2))); - eigenvectors.coeffRef (0) *= norm; - eigenvectors.coeffRef (2) *= norm; - eigenvectors.coeffRef (1) = eigenvectors.coeffRef (2); - eigenvectors.coeffRef (3) = -eigenvectors.coeffRef (0); - } + template void + eigen22 (const Matrix &mat, Matrix &eigenvectors, Vector &eigenvalues); /** \brief determines the corresponding eigenvector to the given eigenvalue of the symmetric positive semi definite input matrix * \param[in] mat symmetric positive semi definite input matrix @@ -262,36 +105,8 @@ namespace pcl * \param[out] eigenvector the corresponding eigenvector for the input eigenvalue * \ingroup common */ - template inline void - computeCorrespondingEigenVector (const Matrix& mat, const typename Matrix::Scalar& eigenvalue, Vector& eigenvector) - { - typedef typename Matrix::Scalar Scalar; - // Scale the matrix so its entries are in [-1,1]. The scaling is applied - // only when at least one matrix entry has magnitude larger than 1. - - Scalar scale = mat.cwiseAbs ().maxCoeff (); - if (scale <= std::numeric_limits::min ()) - scale = Scalar (1.0); - - Matrix scaledMat = mat / scale; - - scaledMat.diagonal ().array () -= eigenvalue / scale; - - Vector vec1 = scaledMat.row (0).cross (scaledMat.row (1)); - Vector vec2 = scaledMat.row (0).cross (scaledMat.row (2)); - Vector vec3 = scaledMat.row (1).cross (scaledMat.row (2)); - - Scalar len1 = vec1.squaredNorm (); - Scalar len2 = vec2.squaredNorm (); - Scalar len3 = vec3.squaredNorm (); - - if (len1 >= len2 && len1 >= len3) - eigenvector = vec1 / std::sqrt (len1); - else if (len2 >= len1 && len2 >= len3) - eigenvector = vec2 / std::sqrt (len2); - else - eigenvector = vec3 / std::sqrt (len3); - } + template void + computeCorrespondingEigenVector (const Matrix &mat, const typename Matrix::Scalar &eigenvalue, Vector &eigenvector); /** \brief determines the eigenvector and eigenvalue of the smallest eigenvalue of the symmetric positive semi definite input matrix * \param[in] mat symmetric positive semi definite input matrix @@ -300,59 +115,16 @@ namespace pcl * \note if the smallest eigenvalue is not unique, this function may return any eigenvector that is consistent to the eigenvalue. * \ingroup common */ - template inline void - eigen33 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenvector) - { - typedef typename Matrix::Scalar Scalar; - // Scale the matrix so its entries are in [-1,1]. The scaling is applied - // only when at least one matrix entry has magnitude larger than 1. - - Scalar scale = mat.cwiseAbs ().maxCoeff (); - if (scale <= std::numeric_limits::min ()) - scale = Scalar (1.0); - - Matrix scaledMat = mat / scale; - - Vector eigenvalues; - computeRoots (scaledMat, eigenvalues); - - eigenvalue = eigenvalues (0) * scale; - - scaledMat.diagonal ().array () -= eigenvalues (0); - - Vector vec1 = scaledMat.row (0).cross (scaledMat.row (1)); - Vector vec2 = scaledMat.row (0).cross (scaledMat.row (2)); - Vector vec3 = scaledMat.row (1).cross (scaledMat.row (2)); - - Scalar len1 = vec1.squaredNorm (); - Scalar len2 = vec2.squaredNorm (); - Scalar len3 = vec3.squaredNorm (); - - if (len1 >= len2 && len1 >= len3) - eigenvector = vec1 / std::sqrt (len1); - else if (len2 >= len1 && len2 >= len3) - eigenvector = vec2 / std::sqrt (len2); - else - eigenvector = vec3 / std::sqrt (len3); - } + template void + eigen33 (const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector); /** \brief determines the eigenvalues of the symmetric positive semi definite input matrix * \param[in] mat symmetric positive semi definite input matrix * \param[out] evals resulting eigenvalues in ascending order * \ingroup common */ - template inline void - eigen33 (const Matrix& mat, Vector& evals) - { - typedef typename Matrix::Scalar Scalar; - Scalar scale = mat.cwiseAbs ().maxCoeff (); - if (scale <= std::numeric_limits::min ()) - scale = Scalar (1.0); - - Matrix scaledMat = mat / scale; - computeRoots (scaledMat, evals); - evals *= scale; - } + template void + eigen33 (const Matrix &mat, Vector &evals); /** \brief determines the eigenvalues and corresponding eigenvectors of the symmetric positive semi definite input matrix * \param[in] mat symmetric positive semi definite input matrix @@ -360,187 +132,8 @@ namespace pcl * \param[out] evals corresponding eigenvectors in correct order according to eigenvalues * \ingroup common */ - template inline void - eigen33 (const Matrix& mat, Matrix& evecs, Vector& evals) - { - typedef typename Matrix::Scalar Scalar; - // Scale the matrix so its entries are in [-1,1]. The scaling is applied - // only when at least one matrix entry has magnitude larger than 1. - - Scalar scale = mat.cwiseAbs ().maxCoeff (); - if (scale <= std::numeric_limits::min ()) - scale = Scalar (1.0); - - Matrix scaledMat = mat / scale; - - // Compute the eigenvalues - computeRoots (scaledMat, evals); - - if ((evals (2) - evals (0)) <= Eigen::NumTraits::epsilon ()) - { - // all three equal - evecs.setIdentity (); - } - else if ((evals (1) - evals (0)) <= Eigen::NumTraits::epsilon () ) - { - // first and second equal - Matrix tmp; - tmp = scaledMat; - tmp.diagonal ().array () -= evals (2); - - Vector vec1 = tmp.row (0).cross (tmp.row (1)); - Vector vec2 = tmp.row (0).cross (tmp.row (2)); - Vector vec3 = tmp.row (1).cross (tmp.row (2)); - - Scalar len1 = vec1.squaredNorm (); - Scalar len2 = vec2.squaredNorm (); - Scalar len3 = vec3.squaredNorm (); - - if (len1 >= len2 && len1 >= len3) - evecs.col (2) = vec1 / std::sqrt (len1); - else if (len2 >= len1 && len2 >= len3) - evecs.col (2) = vec2 / std::sqrt (len2); - else - evecs.col (2) = vec3 / std::sqrt (len3); - - evecs.col (1) = evecs.col (2).unitOrthogonal (); - evecs.col (0) = evecs.col (1).cross (evecs.col (2)); - } - else if ((evals (2) - evals (1)) <= Eigen::NumTraits::epsilon () ) - { - // second and third equal - Matrix tmp; - tmp = scaledMat; - tmp.diagonal ().array () -= evals (0); - - Vector vec1 = tmp.row (0).cross (tmp.row (1)); - Vector vec2 = tmp.row (0).cross (tmp.row (2)); - Vector vec3 = tmp.row (1).cross (tmp.row (2)); - - Scalar len1 = vec1.squaredNorm (); - Scalar len2 = vec2.squaredNorm (); - Scalar len3 = vec3.squaredNorm (); - - if (len1 >= len2 && len1 >= len3) - evecs.col (0) = vec1 / std::sqrt (len1); - else if (len2 >= len1 && len2 >= len3) - evecs.col (0) = vec2 / std::sqrt (len2); - else - evecs.col (0) = vec3 / std::sqrt (len3); - - evecs.col (1) = evecs.col (0).unitOrthogonal (); - evecs.col (2) = evecs.col (0).cross (evecs.col (1)); - } - else - { - Matrix tmp; - tmp = scaledMat; - tmp.diagonal ().array () -= evals (2); - - Vector vec1 = tmp.row (0).cross (tmp.row (1)); - Vector vec2 = tmp.row (0).cross (tmp.row (2)); - Vector vec3 = tmp.row (1).cross (tmp.row (2)); - - Scalar len1 = vec1.squaredNorm (); - Scalar len2 = vec2.squaredNorm (); - Scalar len3 = vec3.squaredNorm (); -#ifdef _WIN32 - Scalar *mmax = new Scalar[3]; -#else - Scalar mmax[3]; -#endif - unsigned int min_el = 2; - unsigned int max_el = 2; - if (len1 >= len2 && len1 >= len3) - { - mmax[2] = len1; - evecs.col (2) = vec1 / std::sqrt (len1); - } - else if (len2 >= len1 && len2 >= len3) - { - mmax[2] = len2; - evecs.col (2) = vec2 / std::sqrt (len2); - } - else - { - mmax[2] = len3; - evecs.col (2) = vec3 / std::sqrt (len3); - } - - tmp = scaledMat; - tmp.diagonal ().array () -= evals (1); - - vec1 = tmp.row (0).cross (tmp.row (1)); - vec2 = tmp.row (0).cross (tmp.row (2)); - vec3 = tmp.row (1).cross (tmp.row (2)); - - len1 = vec1.squaredNorm (); - len2 = vec2.squaredNorm (); - len3 = vec3.squaredNorm (); - if (len1 >= len2 && len1 >= len3) - { - mmax[1] = len1; - evecs.col (1) = vec1 / std::sqrt (len1); - min_el = len1 <= mmax[min_el] ? 1 : min_el; - max_el = len1 > mmax[max_el] ? 1 : max_el; - } - else if (len2 >= len1 && len2 >= len3) - { - mmax[1] = len2; - evecs.col (1) = vec2 / std::sqrt (len2); - min_el = len2 <= mmax[min_el] ? 1 : min_el; - max_el = len2 > mmax[max_el] ? 1 : max_el; - } - else - { - mmax[1] = len3; - evecs.col (1) = vec3 / std::sqrt (len3); - min_el = len3 <= mmax[min_el] ? 1 : min_el; - max_el = len3 > mmax[max_el] ? 1 : max_el; - } - - tmp = scaledMat; - tmp.diagonal ().array () -= evals (0); - - vec1 = tmp.row (0).cross (tmp.row (1)); - vec2 = tmp.row (0).cross (tmp.row (2)); - vec3 = tmp.row (1).cross (tmp.row (2)); - - len1 = vec1.squaredNorm (); - len2 = vec2.squaredNorm (); - len3 = vec3.squaredNorm (); - if (len1 >= len2 && len1 >= len3) - { - mmax[0] = len1; - evecs.col (0) = vec1 / std::sqrt (len1); - min_el = len3 <= mmax[min_el] ? 0 : min_el; - max_el = len3 > mmax[max_el] ? 0 : max_el; - } - else if (len2 >= len1 && len2 >= len3) - { - mmax[0] = len2; - evecs.col (0) = vec2 / std::sqrt (len2); - min_el = len3 <= mmax[min_el] ? 0 : min_el; - max_el = len3 > mmax[max_el] ? 0 : max_el; - } - else - { - mmax[0] = len3; - evecs.col (0) = vec3 / std::sqrt (len3); - min_el = len3 <= mmax[min_el] ? 0 : min_el; - max_el = len3 > mmax[max_el] ? 0 : max_el; - } - - unsigned mid_el = 3 - min_el - max_el; - evecs.col (min_el) = evecs.col ((min_el + 1) % 3).cross ( evecs.col ((min_el + 2) % 3) ).normalized (); - evecs.col (mid_el) = evecs.col ((mid_el + 1) % 3).cross ( evecs.col ((mid_el + 2) % 3) ).normalized (); -#ifdef _WIN32 - delete [] mmax; -#endif - } - // Rescale back to the original size. - evals *= scale; - } + template void + eigen33 (const Matrix &mat, Matrix &evecs, Vector &evals); /** \brief Calculate the inverse of a 2x2 matrix * \param[in] matrix matrix to be inverted @@ -549,23 +142,8 @@ namespace pcl * \return determinant of the original matrix => if 0 no inverse exists => result is invalid * \ingroup common */ - template inline typename Matrix::Scalar - invert2x2 (const Matrix& matrix, Matrix& inverse) - { - typedef typename Matrix::Scalar Scalar; - Scalar det = matrix.coeff (0) * matrix.coeff (3) - matrix.coeff (1) * matrix.coeff (2) ; - - if (det != 0) - { - //Scalar inv_det = Scalar (1.0) / det; - inverse.coeffRef (0) = matrix.coeff (3); - inverse.coeffRef (1) = - matrix.coeff (1); - inverse.coeffRef (2) = - matrix.coeff (2); - inverse.coeffRef (3) = matrix.coeff (0); - inverse /= det; - } - return det; - } + template typename Matrix::Scalar + invert2x2 (const Matrix &matrix, Matrix &inverse); /** \brief Calculate the inverse of a 3x3 symmetric matrix. * \param[in] matrix matrix to be inverted @@ -574,39 +152,8 @@ namespace pcl * \return determinant of the original matrix => if 0 no inverse exists => result is invalid * \ingroup common */ - template inline typename Matrix::Scalar - invert3x3SymMatrix (const Matrix& matrix, Matrix& inverse) - { - typedef typename Matrix::Scalar Scalar; - // elements - // a b c - // b d e - // c e f - //| a b c |-1 | fd-ee ce-bf be-cd | - //| b d e | = 1/det * | ce-bf af-cc bc-ae | - //| c e f | | be-cd bc-ae ad-bb | - - //det = a(fd-ee) + b(ec-fb) + c(eb-dc) - - Scalar fd_ee = matrix.coeff (4) * matrix.coeff (8) - matrix.coeff (7) * matrix.coeff (5); - Scalar ce_bf = matrix.coeff (2) * matrix.coeff (5) - matrix.coeff (1) * matrix.coeff (8); - Scalar be_cd = matrix.coeff (1) * matrix.coeff (5) - matrix.coeff (2) * matrix.coeff (4); - - Scalar det = matrix.coeff (0) * fd_ee + matrix.coeff (1) * ce_bf + matrix.coeff (2) * be_cd; - - if (det != 0) - { - //Scalar inv_det = Scalar (1.0) / det; - inverse.coeffRef (0) = fd_ee; - inverse.coeffRef (1) = inverse.coeffRef (3) = ce_bf; - inverse.coeffRef (2) = inverse.coeffRef (6) = be_cd; - inverse.coeffRef (4) = (matrix.coeff (0) * matrix.coeff (8) - matrix.coeff (2) * matrix.coeff (2)); - inverse.coeffRef (5) = inverse.coeffRef (7) = (matrix.coeff (1) * matrix.coeff (2) - matrix.coeff (0) * matrix.coeff (5)); - inverse.coeffRef (8) = (matrix.coeff (0) * matrix.coeff (4) - matrix.coeff (1) * matrix.coeff (1)); - inverse /= det; - } - return det; - } + template typename Matrix::Scalar + invert3x3SymMatrix (const Matrix &matrix, Matrix &inverse); /** \brief Calculate the inverse of a general 3x3 matrix. * \param[in] matrix matrix to be inverted @@ -614,46 +161,16 @@ namespace pcl * \return determinant of the original matrix => if 0 no inverse exists => result is invalid * \ingroup common */ - template inline typename Matrix::Scalar - invert3x3Matrix (const Matrix& matrix, Matrix& inverse) - { - typedef typename Matrix::Scalar Scalar; - - //| a b c |-1 | ie-hf hc-ib fb-ec | - //| d e f | = 1/det * | gf-id ia-gc dc-fa | - //| g h i | | hd-ge gb-ha ea-db | - //det = a(ie-hf) + d(hc-ib) + g(fb-ec) - - Scalar ie_hf = matrix.coeff (8) * matrix.coeff (4) - matrix.coeff (7) * matrix.coeff (5); - Scalar hc_ib = matrix.coeff (7) * matrix.coeff (2) - matrix.coeff (8) * matrix.coeff (1); - Scalar fb_ec = matrix.coeff (5) * matrix.coeff (1) - matrix.coeff (4) * matrix.coeff (2); - Scalar det = matrix.coeff (0) * (ie_hf) + matrix.coeff (3) * (hc_ib) + matrix.coeff (6) * (fb_ec) ; - - if (det != 0) - { - inverse.coeffRef (0) = ie_hf; - inverse.coeffRef (1) = hc_ib; - inverse.coeffRef (2) = fb_ec; - inverse.coeffRef (3) = matrix.coeff (6) * matrix.coeff (5) - matrix.coeff (8) * matrix.coeff (3); - inverse.coeffRef (4) = matrix.coeff (8) * matrix.coeff (0) - matrix.coeff (6) * matrix.coeff (2); - inverse.coeffRef (5) = matrix.coeff (3) * matrix.coeff (2) - matrix.coeff (5) * matrix.coeff (0); - inverse.coeffRef (6) = matrix.coeff (7) * matrix.coeff (3) - matrix.coeff (6) * matrix.coeff (4); - inverse.coeffRef (7) = matrix.coeff (6) * matrix.coeff (1) - matrix.coeff (7) * matrix.coeff (0); - inverse.coeffRef (8) = matrix.coeff (4) * matrix.coeff (0) - matrix.coeff (3) * matrix.coeff (1); - - inverse /= det; - } - return det; - } + template typename Matrix::Scalar + invert3x3Matrix (const Matrix &matrix, Matrix &inverse); - template inline typename Matrix::Scalar - determinant3x3Matrix (const Matrix& matrix) - { - // result is independent of Row/Col Major storage! - return matrix.coeff (0) * (matrix.coeff (4) * matrix.coeff (8) - matrix.coeff (5) * matrix.coeff (7)) + - matrix.coeff (1) * (matrix.coeff (5) * matrix.coeff (6) - matrix.coeff (3) * matrix.coeff (8)) + - matrix.coeff (2) * (matrix.coeff (3) * matrix.coeff (7) - matrix.coeff (4) * matrix.coeff (6)) ; - } + /** \brief Calculate the determinant of a 3x3 matrix. + * \param[in] matrix matrix + * \return determinant of the matrix + * \ingroup common + */ + template typename Matrix::Scalar + determinant3x3Matrix (const Matrix &matrix); /** \brief Get the unique 3D rotation that will rotate \a z_axis into (0,0,1) and \a y_direction into a vector * with x=0 (or into (0,1,0) should \a y_direction be orthogonal to \a z_axis) @@ -745,8 +262,20 @@ namespace pcl * \param[in] yaw the resulting yaw angle * \ingroup common */ + template void + getEulerAngles (const Eigen::Transform &t, Scalar &roll, Scalar &pitch, Scalar &yaw); + + inline void + getEulerAngles (const Eigen::Affine3f &t, float &roll, float &pitch, float &yaw) + { + getEulerAngles (t, roll, pitch, yaw); + } + inline void - getEulerAngles (const Eigen::Affine3f& t, float& roll, float& pitch, float& yaw); + getEulerAngles (const Eigen::Affine3d &t, double &roll, double &pitch, double &yaw) + { + getEulerAngles (t, roll, pitch, yaw); + } /** Extract x,y,z and the Euler angles (XYZ-convention) from the given transformation * \param[in] t the input transformation matrix @@ -758,10 +287,26 @@ namespace pcl * \param[out] yaw the resulting yaw angle * \ingroup common */ + template void + getTranslationAndEulerAngles (const Eigen::Transform &t, + Scalar &x, Scalar &y, Scalar &z, + Scalar &roll, Scalar &pitch, Scalar &yaw); + + inline void + getTranslationAndEulerAngles (const Eigen::Affine3f &t, + float &x, float &y, float &z, + float &roll, float &pitch, float &yaw) + { + getTranslationAndEulerAngles (t, x, y, z, roll, pitch, yaw); + } + inline void - getTranslationAndEulerAngles (const Eigen::Affine3f& t, - float& x, float& y, float& z, - float& roll, float& pitch, float& yaw); + getTranslationAndEulerAngles (const Eigen::Affine3d &t, + double &x, double &y, double &z, + double &roll, double &pitch, double &yaw) + { + getTranslationAndEulerAngles (t, x, y, z, roll, pitch, yaw); + } /** \brief Create a transformation from the given translation and Euler angles (XYZ-convention) * \param[in] x the input x translation @@ -773,7 +318,7 @@ namespace pcl * \param[out] t the resulting transformation matrix * \ingroup common */ - template inline void + template void getTransformation (Scalar x, Scalar y, Scalar z, Scalar roll, Scalar pitch, Scalar yaw, Eigen::Transform &t); @@ -802,7 +347,12 @@ namespace pcl * \ingroup common */ inline Eigen::Affine3f - getTransformation (float x, float y, float z, float roll, float pitch, float yaw); + getTransformation (float x, float y, float z, float roll, float pitch, float yaw) + { + Eigen::Affine3f t; + getTransformation (x, y, z, roll, pitch, yaw, t); + return (t); + } /** \brief Write a matrix to an output stream * \param[in] matrix the matrix to output @@ -861,6 +411,306 @@ namespace pcl template typename Eigen::internal::umeyama_transform_matrix_type::type umeyama (const Eigen::MatrixBase& src, const Eigen::MatrixBase& dst, bool with_scaling = false); + +/** \brief Transform a point using an affine matrix + * \param[in] point_in the vector to be transformed + * \param[out] point_out the transformed vector + * \param[in] transformation the transformation matrix + * + * \note Can be used with \c point_in = \c point_out + */ + template inline void + transformPoint (const Eigen::Matrix &point_in, + Eigen::Matrix &point_out, + const Eigen::Transform &transformation) + { + Eigen::Matrix point; + point << point_in, 1.0; + point_out = (transformation * point).template head<3> (); + } + + inline void + transformPoint (const Eigen::Vector3f &point_in, + Eigen::Vector3f &point_out, + const Eigen::Affine3f &transformation) + { + transformPoint (point_in, point_out, transformation); + } + + inline void + transformPoint (const Eigen::Vector3d &point_in, + Eigen::Vector3d &point_out, + const Eigen::Affine3d &transformation) + { + transformPoint (point_in, point_out, transformation); + } + +/** \brief Transform a vector using an affine matrix + * \param[in] vector_in the vector to be transformed + * \param[out] vector_out the transformed vector + * \param[in] transformation the transformation matrix + * + * \note Can be used with \c vector_in = \c vector_out + */ + template inline void + transformVector (const Eigen::Matrix &vector_in, + Eigen::Matrix &vector_out, + const Eigen::Transform &transformation) + { + vector_out = transformation.linear () * vector_in; + } + + inline void + transformVector (const Eigen::Vector3f &vector_in, + Eigen::Vector3f &vector_out, + const Eigen::Affine3f &transformation) + { + transformVector (vector_in, vector_out, transformation); + } + + inline void + transformVector (const Eigen::Vector3d &vector_in, + Eigen::Vector3d &vector_out, + const Eigen::Affine3d &transformation) + { + transformVector (vector_in, vector_out, transformation); + } + +/** \brief Transform a line using an affine matrix + * \param[in] line_in the line to be transformed + * \param[out] line_out the transformed line + * \param[in] transformation the transformation matrix + * + * Lines must be filled in this form:\n + * line[0-2] = Origin coordinates of the vector\n + * line[3-5] = Direction vector + * + * \note Can be used with \c line_in = \c line_out + */ + template bool + transformLine (const Eigen::Matrix &line_in, + Eigen::Matrix &line_out, + const Eigen::Transform &transformation); + + inline bool + transformLine (const Eigen::VectorXf &line_in, + Eigen::VectorXf &line_out, + const Eigen::Affine3f &transformation) + { + return (transformLine (line_in, line_out, transformation)); + } + + inline bool + transformLine (const Eigen::VectorXd &line_in, + Eigen::VectorXd &line_out, + const Eigen::Affine3d &transformation) + { + return (transformLine (line_in, line_out, transformation)); + } + +/** \brief Transform plane vectors using an affine matrix + * \param[in] plane_in the plane coefficients to be transformed + * \param[out] plane_out the transformed plane coefficients to fill + * \param[in] transformation the transformation matrix + * + * The plane vectors are filled in the form ax+by+cz+d=0 + * Can be used with non Hessian form planes coefficients + * Can be used with \c plane_in = \c plane_out + */ + template void + transformPlane (const Eigen::Matrix &plane_in, + Eigen::Matrix &plane_out, + const Eigen::Transform &transformation); + + inline void + transformPlane (const Eigen::Matrix &plane_in, + Eigen::Matrix &plane_out, + const Eigen::Transform &transformation) + { + transformPlane (plane_in, plane_out, transformation); + } + + inline void + transformPlane (const Eigen::Matrix &plane_in, + Eigen::Matrix &plane_out, + const Eigen::Transform &transformation) + { + transformPlane (plane_in, plane_out, transformation); + } + +/** \brief Transform plane vectors using an affine matrix + * \param[in] plane_in the plane coefficients to be transformed + * \param[out] plane_out the transformed plane coefficients to fill + * \param[in] transformation the transformation matrix + * + * The plane vectors are filled in the form ax+by+cz+d=0 + * Can be used with non Hessian form planes coefficients + * Can be used with \c plane_in = \c plane_out + * \warning ModelCoefficients stores floats only ! + */ + template void + transformPlane (const pcl::ModelCoefficients::Ptr plane_in, + pcl::ModelCoefficients::Ptr plane_out, + const Eigen::Transform &transformation); + + inline void + transformPlane (const pcl::ModelCoefficients::Ptr plane_in, + pcl::ModelCoefficients::Ptr plane_out, + const Eigen::Transform &transformation) + { + transformPlane (plane_in, plane_out, transformation); + } + + inline void + transformPlane (const pcl::ModelCoefficients::Ptr plane_in, + pcl::ModelCoefficients::Ptr plane_out, + const Eigen::Transform &transformation) + { + transformPlane (plane_in, plane_out, transformation); + } + +/** \brief Check coordinate system integrity + * \param[in] line_x the first axis + * \param[in] line_y the second axis + * \param[in] norm_limit the limit to ignore norm rounding errors + * \param[in] dot_limit the limit to ignore dot product rounding errors + * \return True if the coordinate system is consistent, false otherwise. + * + * Lines must be filled in this form:\n + * line[0-2] = Origin coordinates of the vector\n + * line[3-5] = Direction vector + * + * Can be used like this :\n + * line_x = X axis and line_y = Y axis\n + * line_x = Z axis and line_y = X axis\n + * line_x = Y axis and line_y = Z axis\n + * Because X^Y = Z, Z^X = Y and Y^Z = X. + * Do NOT invert line order ! + * + * Determine whether a coordinate system is consistent or not by checking :\n + * Line origins: They must be the same for the 2 lines\n + * Norm: The 2 lines must be normalized\n + * Dot products: Must be 0 or perpendicular vectors + */ + template bool + checkCoordinateSystem (const Eigen::Matrix &line_x, + const Eigen::Matrix &line_y, + const Scalar norm_limit = 1e-3, + const Scalar dot_limit = 1e-3); + + inline bool + checkCoordinateSystem (const Eigen::Matrix &line_x, + const Eigen::Matrix &line_y, + const double norm_limit = 1e-3, + const double dot_limit = 1e-3) + { + return (checkCoordinateSystem (line_x, line_y, norm_limit, dot_limit)); + } + + inline bool + checkCoordinateSystem (const Eigen::Matrix &line_x, + const Eigen::Matrix &line_y, + const float norm_limit = 1e-3, + const float dot_limit = 1e-3) + { + return (checkCoordinateSystem (line_x, line_y, norm_limit, dot_limit)); + } + +/** \brief Check coordinate system integrity + * \param[in] origin the origin of the coordinate system + * \param[in] x_direction the first axis + * \param[in] y_direction the second axis + * \param[in] norm_limit the limit to ignore norm rounding errors + * \param[in] dot_limit the limit to ignore dot product rounding errors + * \return True if the coordinate system is consistent, false otherwise. + * + * Read the other variant for more information + */ + template inline bool + checkCoordinateSystem (const Eigen::Matrix &origin, + const Eigen::Matrix &x_direction, + const Eigen::Matrix &y_direction, + const Scalar norm_limit = 1e-3, + const Scalar dot_limit = 1e-3) + { + Eigen::Matrix line_x; + Eigen::Matrix line_y; + line_x << origin, x_direction; + line_y << origin, y_direction; + return (checkCoordinateSystem (line_x, line_y, norm_limit, dot_limit)); + } + + inline bool + checkCoordinateSystem (const Eigen::Matrix &origin, + const Eigen::Matrix &x_direction, + const Eigen::Matrix &y_direction, + const double norm_limit = 1e-3, + const double dot_limit = 1e-3) + { + Eigen::Matrix line_x; + Eigen::Matrix line_y; + line_x.resize (6); + line_y.resize (6); + line_x << origin, x_direction; + line_y << origin, y_direction; + return (checkCoordinateSystem (line_x, line_y, norm_limit, dot_limit)); + } + + inline bool + checkCoordinateSystem (const Eigen::Matrix &origin, + const Eigen::Matrix &x_direction, + const Eigen::Matrix &y_direction, + const float norm_limit = 1e-3, + const float dot_limit = 1e-3) + { + Eigen::Matrix line_x; + Eigen::Matrix line_y; + line_x.resize (6); + line_y.resize (6); + line_x << origin, x_direction; + line_y << origin, y_direction; + return (checkCoordinateSystem (line_x, line_y, norm_limit, dot_limit)); + } + +/** \brief Compute the transformation between two coordinate systems + * \param[in] from_line_x X axis from the origin coordinate system + * \param[in] from_line_y Y axis from the origin coordinate system + * \param[in] to_line_x X axis from the destination coordinate system + * \param[in] to_line_y Y axis from the destination coordinate system + * \param[out] transformation the transformation matrix to fill + * \return true if transformation was filled, false otherwise. + * + * Line must be filled in this form:\n + * line[0-2] = Coordinate system origin coordinates \n + * line[3-5] = Direction vector (norm doesn't matter) + */ + template bool + transformBetween2CoordinateSystems (const Eigen::Matrix from_line_x, + const Eigen::Matrix from_line_y, + const Eigen::Matrix to_line_x, + const Eigen::Matrix to_line_y, + Eigen::Transform &transformation); + + inline bool + transformBetween2CoordinateSystems (const Eigen::Matrix from_line_x, + const Eigen::Matrix from_line_y, + const Eigen::Matrix to_line_x, + const Eigen::Matrix to_line_y, + Eigen::Transform &transformation) + { + return (transformBetween2CoordinateSystems (from_line_x, from_line_y, to_line_x, to_line_y, transformation)); + } + + inline bool + transformBetween2CoordinateSystems (const Eigen::Matrix from_line_x, + const Eigen::Matrix from_line_y, + const Eigen::Matrix to_line_x, + const Eigen::Matrix to_line_y, + Eigen::Transform &transformation) + { + return (transformBetween2CoordinateSystems (from_line_x, from_line_y, to_line_x, to_line_y, transformation)); + } + } #include diff --git a/common/include/pcl/common/impl/accumulators.hpp b/common/include/pcl/common/impl/accumulators.hpp new file mode 100644 index 00000000..7c0b8873 --- /dev/null +++ b/common/include/pcl/common/impl/accumulators.hpp @@ -0,0 +1,296 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2014-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PCL_COMMON_IMPL_DETAIL_ACCUMULATORS_HPP +#define PCL_COMMON_IMPL_DETAIL_ACCUMULATORS_HPP + +#include + +#include +#include +#include +#include + +#include + +namespace pcl +{ + + namespace detail + { + + /* Below are several helper accumulator structures that are used by the + * `CentroidPoint` class. Each of them is capable of accumulating + * information from a particular field(s) of a point. The points are + * inserted via `add()` and extracted via `get()` functions. Note that the + * accumulators are not templated on point type, so in principle it is + * possible to insert and extract points of different types. It is the + * responsibility of the user to make sure that points have corresponding + * fields. */ + + struct AccumulatorXYZ + { + + // Requires that point type has x, y, and z fields + typedef pcl::traits::has_xyz IsCompatible; + + // Storage + Eigen::Vector3f xyz; + + AccumulatorXYZ () : xyz (Eigen::Vector3f::Zero ()) { } + + template void + add (const PointT& t) { xyz += t.getVector3fMap (); } + + template void + get (PointT& t, size_t n) const { t.getVector3fMap () = xyz / n; } + + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + }; + + struct AccumulatorNormal + { + + // Requires that point type has normal_x, normal_y, and normal_z fields + typedef pcl::traits::has_normal IsCompatible; + + // Storage + Eigen::Vector4f normal; + + AccumulatorNormal () : normal (Eigen::Vector4f::Zero ()) { } + + // Requires that the normal of the given point is normalized, otherwise it + // does not make sense to sum it up with the accumulated value. + template void + add (const PointT& t) { normal += t.getNormalVector4fMap (); } + + template void + get (PointT& t, size_t) const + { + t.getNormalVector4fMap () = normal; + t.getNormalVector4fMap ().normalize (); + } + + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + }; + + struct AccumulatorCurvature + { + + // Requires that point type has curvature field + typedef pcl::traits::has_curvature IsCompatible; + + // Storage + float curvature; + + AccumulatorCurvature () : curvature (0) { } + + template void + add (const PointT& t) { curvature += t.curvature; } + + template void + get (PointT& t, size_t n) const { t.curvature = curvature / n; } + + }; + + struct AccumulatorRGBA + { + + // Requires that point type has rgb or rgba field + typedef pcl::traits::has_color IsCompatible; + + // Storage + float r, g, b, a; + + AccumulatorRGBA () : r (0), g (0), b (0), a (0) { } + + template void + add (const PointT& t) + { + r += static_cast (t.r); + g += static_cast (t.g); + b += static_cast (t.b); + a += static_cast (t.a); + } + + template void + get (PointT& t, size_t n) const + { + t.rgba = static_cast (a / n) << 24 | + static_cast (r / n) << 16 | + static_cast (g / n) << 8 | + static_cast (b / n); + } + + }; + + struct AccumulatorIntensity + { + + // Requires that point type has intensity field + typedef pcl::traits::has_intensity IsCompatible; + + // Storage + float intensity; + + AccumulatorIntensity () : intensity (0) { } + + template void + add (const PointT& t) { intensity += t.intensity; } + + template void + get (PointT& t, size_t n) const { t.intensity = intensity / n; } + + }; + + struct AccumulatorLabel + { + + // Requires that point type has label field + typedef pcl::traits::has_label IsCompatible; + + // Storage + // A better performance may be achieved with a heap structure + std::map labels; + + AccumulatorLabel () { } + + template void + add (const PointT& t) + { + std::map::iterator itr = labels.find (t.label); + if (itr == labels.end ()) + labels.insert (std::make_pair (t.label, 1)); + else + ++itr->second; + } + + template void + get (PointT& t, size_t) const + { + size_t max = 0; + std::map::const_iterator itr; + for (itr = labels.begin (); itr != labels.end (); ++itr) + if (itr->second > max) + { + max = itr->second; + t.label = itr->first; + } + } + + }; + + /* This is a meta-function that may be used to create a Fusion vector of + * those accumulator types that are compatible with given point type(s). */ + + template + struct Accumulators + { + + // Check if a given accumulator type is compatible with a given point type + template + struct IsCompatible : boost::mpl::apply { }; + + // A Fusion vector with accumulator types that are compatible with given + // point types + typedef + typename boost::fusion::result_of::as_vector< + typename boost::mpl::filter_view< + boost::mpl::vector< + AccumulatorXYZ + , AccumulatorNormal + , AccumulatorCurvature + , AccumulatorRGBA + , AccumulatorIntensity + , AccumulatorLabel + > + , boost::mpl::and_< + IsCompatible + , IsCompatible + > + > + >::type + type; + }; + + /* Fusion function object to invoke point addition on every accumulator in + * a fusion sequence. */ + + template + struct AddPoint + { + + const PointT& p; + + AddPoint (const PointT& point) : p (point) { } + + template void + operator () (AccumulatorT& accumulator) const + { + accumulator.add (p); + } + + }; + + /* Fusion function object to invoke get point on every accumulator in a + * fusion sequence. */ + + template + struct GetPoint + { + + PointT& p; + size_t n; + + GetPoint (PointT& point, size_t num) : p (point), n (num) { } + + template void + operator () (AccumulatorT& accumulator) const + { + accumulator.get (p, n); + } + + }; + + } + +} + +#endif /* PCL_COMMON_IMPL_DETAIL_ACCUMULATORS_HPP */ + diff --git a/common/include/pcl/common/impl/centroid.hpp b/common/include/pcl/common/impl/centroid.hpp index 22a04e48..2c13eb10 100644 --- a/common/include/pcl/common/impl/centroid.hpp +++ b/common/include/pcl/common/impl/centroid.hpp @@ -70,8 +70,8 @@ pcl::compute3DCentroid (ConstCloudIterator &cloud_iterator, ++cp; ++cloud_iterator; } - centroid[3] = 0; centroid /= static_cast (cp); + centroid[3] = 1; return (cp); } @@ -95,8 +95,8 @@ pcl::compute3DCentroid (const pcl::PointCloud &cloud, centroid[1] += cloud[i].y; centroid[2] += cloud[i].z; } - centroid[3] = 0; centroid /= static_cast (cloud.size ()); + centroid[3] = 1; return (static_cast (cloud.size ())); } @@ -115,8 +115,8 @@ pcl::compute3DCentroid (const pcl::PointCloud &cloud, centroid[2] += cloud[i].z; ++cp; } - centroid[3] = 0; centroid /= static_cast (cp); + centroid[3] = 1; return (cp); } @@ -142,8 +142,8 @@ pcl::compute3DCentroid (const pcl::PointCloud &cloud, centroid[1] += cloud[indices[i]].y; centroid[2] += cloud[indices[i]].z; } - centroid[3] = 0; centroid /= static_cast (indices.size ()); + centroid[3] = 1; return (static_cast (indices.size ())); } // NaN or Inf values could exist => check for them @@ -161,8 +161,8 @@ pcl::compute3DCentroid (const pcl::PointCloud &cloud, centroid[2] += cloud[indices[i]].z; ++cp; } - centroid[3] = 0; centroid /= static_cast (cp); + centroid[3] = 1; return (cp); } } @@ -536,7 +536,7 @@ pcl::computeMeanAndCovarianceMatrix (const pcl::PointCloud &cloud, { //centroid.head<3> () = accu.tail<3> (); -- does not compile with Clang 3.0 centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8]; - centroid[3] = 0; + centroid[3] = 1; covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6]; covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7]; covariance_matrix.coeffRef (2) = accu [2] - accu [6] * accu [8]; @@ -603,7 +603,7 @@ pcl::computeMeanAndCovarianceMatrix (const pcl::PointCloud &cloud, //centroid.head<3> () = vec;//= accu.tail<3> (); //centroid.head<3> () = accu.tail<3> (); -- does not compile with Clang 3.0 centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8]; - centroid[3] = 0; + centroid[3] = 1; covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6]; covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7]; covariance_matrix.coeffRef (2) = accu [2] - accu [6] * accu [8]; @@ -859,5 +859,44 @@ pcl::computeNDCentroid (const pcl::PointCloud &cloud, return (pcl::computeNDCentroid (cloud, indices.indices, centroid)); } +///////////////////////////////////////////////////////////////////////////////////////////// +template size_t +pcl::computeCentroid (const pcl::PointCloud& cloud, + PointOutT& centroid) +{ + pcl::CentroidPoint cp; + + if (cloud.is_dense) + for (size_t i = 0; i < cloud.size (); ++i) + cp.add (cloud[i]); + else + for (size_t i = 0; i < cloud.size (); ++i) + if (pcl::isFinite (cloud[i])) + cp.add (cloud[i]); + + cp.get (centroid); + return (cp.getSize ()); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +template size_t +pcl::computeCentroid (const pcl::PointCloud& cloud, + const std::vector& indices, + PointOutT& centroid) +{ + pcl::CentroidPoint cp; + + if (cloud.is_dense) + for (size_t i = 0; i < indices.size (); ++i) + cp.add (cloud[indices[i]]); + else + for (size_t i = 0; i < indices.size (); ++i) + if (pcl::isFinite (cloud[indices[i]])) + cp.add (cloud[indices[i]]); + + cp.get (centroid); + return (cp.getSize ()); +} + #endif //#ifndef PCL_COMMON_IMPL_CENTROID_H_ diff --git a/common/include/pcl/common/impl/copy_point.hpp b/common/include/pcl/common/impl/copy_point.hpp new file mode 100644 index 00000000..b4070a0e --- /dev/null +++ b/common/include/pcl/common/impl/copy_point.hpp @@ -0,0 +1,145 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2014-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PCL_COMMON_IMPL_COPY_POINT_HPP_ +#define PCL_COMMON_IMPL_COPY_POINT_HPP_ + +#include +#include +#include +#include + +namespace pcl +{ + + namespace detail + { + + /* CopyPointHelper and its specializations copy the contents of a source + * point to a target point. There are three cases: + * + * - Points have the same type. + * In this case a single `memcpy` is used. + * + * - Points have different types and one of the following is true: + * * both have RGB fields; + * * both have RGBA fields; + * * one or both have no RGB/RGBA fields. + * In this case we find the list of common fields and copy their + * contents one by one with `NdConcatenateFunctor`. + * + * - Points have different types and one of these types has RGB field, and + * the other has RGBA field. + * In this case we also find the list of common fields and copy their + * contents. In order to account for the fact that RGB and RGBA do not + * match we have an additional `memcpy` to copy the contents of one into + * another. + * + * An appropriate version of CopyPointHelper is instantiated during + * compilation time automatically, so there is absolutely no run-time + * overhead. */ + + template + struct CopyPointHelper { }; + + template + struct CopyPointHelper >::type> + { + void operator () (const PointInT& point_in, PointOutT& point_out) const + { + memcpy (&point_out, &point_in, sizeof (PointInT)); + } + }; + + template + struct CopyPointHelper >, + boost::mpl::or_ >, + boost::mpl::not_ >, + boost::mpl::and_, + pcl::traits::has_field >, + boost::mpl::and_, + pcl::traits::has_field > > > >::type> + { + void operator () (const PointInT& point_in, PointOutT& point_out) const + { + typedef typename pcl::traits::fieldList::type FieldListInT; + typedef typename pcl::traits::fieldList::type FieldListOutT; + typedef typename pcl::intersect::type FieldList; + pcl::for_each_type (pcl::NdConcatenateFunctor (point_in, point_out)); + } + }; + + template + struct CopyPointHelper >, + boost::mpl::or_, + pcl::traits::has_field >, + boost::mpl::and_, + pcl::traits::has_field > > > >::type> + { + void operator () (const PointInT& point_in, PointOutT& point_out) const + { + typedef typename pcl::traits::fieldList::type FieldListInT; + typedef typename pcl::traits::fieldList::type FieldListOutT; + typedef typename pcl::intersect::type FieldList; + const uint32_t offset_in = boost::mpl::if_, + pcl::traits::offset, + pcl::traits::offset >::type::value; + const uint32_t offset_out = boost::mpl::if_, + pcl::traits::offset, + pcl::traits::offset >::type::value; + pcl::for_each_type (pcl::NdConcatenateFunctor (point_in, point_out)); + memcpy (reinterpret_cast (&point_out) + offset_out, + reinterpret_cast (&point_in) + offset_in, + 4); + } + }; + + } + +} + +template void +pcl::copyPoint (const PointInT& point_in, PointOutT& point_out) +{ + detail::CopyPointHelper copy; + copy (point_in, point_out); +} + +#endif //PCL_COMMON_IMPL_COPY_POINT_HPP_ + diff --git a/common/include/pcl/common/impl/eigen.hpp b/common/include/pcl/common/impl/eigen.hpp index c9175b58..552224e6 100644 --- a/common/include/pcl/common/impl/eigen.hpp +++ b/common/include/pcl/common/impl/eigen.hpp @@ -39,7 +39,543 @@ #ifndef PCL_COMMON_EIGEN_IMPL_HPP_ #define PCL_COMMON_EIGEN_IMPL_HPP_ -#include +#include + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::computeRoots2 (const Scalar& b, const Scalar& c, Roots& roots) +{ + roots (0) = Scalar (0); + Scalar d = Scalar (b * b - 4.0 * c); + if (d < 0.0) // no real roots ! THIS SHOULD NOT HAPPEN! + d = 0.0; + + Scalar sd = ::std::sqrt (d); + + roots (2) = 0.5f * (b + sd); + roots (1) = 0.5f * (b - sd); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::computeRoots (const Matrix& m, Roots& roots) +{ + typedef typename Matrix::Scalar Scalar; + + // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The + // eigenvalues are the roots to this equation, all guaranteed to be + // real-valued, because the matrix is symmetric. + Scalar c0 = m (0, 0) * m (1, 1) * m (2, 2) + + Scalar (2) * m (0, 1) * m (0, 2) * m (1, 2) + - m (0, 0) * m (1, 2) * m (1, 2) + - m (1, 1) * m (0, 2) * m (0, 2) + - m (2, 2) * m (0, 1) * m (0, 1); + Scalar c1 = m (0, 0) * m (1, 1) - + m (0, 1) * m (0, 1) + + m (0, 0) * m (2, 2) - + m (0, 2) * m (0, 2) + + m (1, 1) * m (2, 2) - + m (1, 2) * m (1, 2); + Scalar c2 = m (0, 0) + m (1, 1) + m (2, 2); + + if (fabs (c0) < Eigen::NumTraits < Scalar > ::epsilon ()) // one root is 0 -> quadratic equation + computeRoots2 (c2, c1, roots); + else + { + const Scalar s_inv3 = Scalar (1.0 / 3.0); + const Scalar s_sqrt3 = std::sqrt (Scalar (3.0)); + // Construct the parameters used in classifying the roots of the equation + // and in solving the equation for the roots in closed form. + Scalar c2_over_3 = c2 * s_inv3; + Scalar a_over_3 = (c1 - c2 * c2_over_3) * s_inv3; + if (a_over_3 > Scalar (0)) + a_over_3 = Scalar (0); + + Scalar half_b = Scalar (0.5) * (c0 + c2_over_3 * (Scalar (2) * c2_over_3 * c2_over_3 - c1)); + + Scalar q = half_b * half_b + a_over_3 * a_over_3 * a_over_3; + if (q > Scalar (0)) + q = Scalar (0); + + // Compute the eigenvalues by solving for the roots of the polynomial. + Scalar rho = std::sqrt (-a_over_3); + Scalar theta = std::atan2 (std::sqrt (-q), half_b) * s_inv3; + Scalar cos_theta = std::cos (theta); + Scalar sin_theta = std::sin (theta); + roots (0) = c2_over_3 + Scalar (2) * rho * cos_theta; + roots (1) = c2_over_3 - rho * (cos_theta + s_sqrt3 * sin_theta); + roots (2) = c2_over_3 - rho * (cos_theta - s_sqrt3 * sin_theta); + + // Sort in increasing order. + if (roots (0) >= roots (1)) + std::swap (roots (0), roots (1)); + if (roots (1) >= roots (2)) + { + std::swap (roots (1), roots (2)); + if (roots (0) >= roots (1)) + std::swap (roots (0), roots (1)); + } + + if (roots (0) <= 0) // eigenval for symetric positive semi-definite matrix can not be negative! Set it to 0 + computeRoots2 (c2, c1, roots); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::eigen22 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenvector) +{ + // if diagonal matrix, the eigenvalues are the diagonal elements + // and the eigenvectors are not unique, thus set to Identity + if (fabs (mat.coeff (1)) <= std::numeric_limits::min ()) + { + if (mat.coeff (0) < mat.coeff (2)) + { + eigenvalue = mat.coeff (0); + eigenvector[0] = 1.0; + eigenvector[1] = 0.0; + } + else + { + eigenvalue = mat.coeff (2); + eigenvector[0] = 0.0; + eigenvector[1] = 1.0; + } + return; + } + + // 0.5 to optimize further calculations + typename Matrix::Scalar trace = static_cast (0.5) * (mat.coeff (0) + mat.coeff (3)); + typename Matrix::Scalar determinant = mat.coeff (0) * mat.coeff (3) - mat.coeff (1) * mat.coeff (1); + + typename Matrix::Scalar temp = trace * trace - determinant; + + if (temp < 0) + temp = 0; + + eigenvalue = trace - ::std::sqrt (temp); + + eigenvector[0] = -mat.coeff (1); + eigenvector[1] = mat.coeff (0) - eigenvalue; + eigenvector.normalize (); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::eigen22 (const Matrix& mat, Matrix& eigenvectors, Vector& eigenvalues) +{ + // if diagonal matrix, the eigenvalues are the diagonal elements + // and the eigenvectors are not unique, thus set to Identity + if (fabs (mat.coeff (1)) <= std::numeric_limits::min ()) + { + if (mat.coeff (0) < mat.coeff (3)) + { + eigenvalues.coeffRef (0) = mat.coeff (0); + eigenvalues.coeffRef (1) = mat.coeff (3); + eigenvectors.coeffRef (0) = 1.0; + eigenvectors.coeffRef (1) = 0.0; + eigenvectors.coeffRef (2) = 0.0; + eigenvectors.coeffRef (3) = 1.0; + } + else + { + eigenvalues.coeffRef (0) = mat.coeff (3); + eigenvalues.coeffRef (1) = mat.coeff (0); + eigenvectors.coeffRef (0) = 0.0; + eigenvectors.coeffRef (1) = 1.0; + eigenvectors.coeffRef (2) = 1.0; + eigenvectors.coeffRef (3) = 0.0; + } + return; + } + + // 0.5 to optimize further calculations + typename Matrix::Scalar trace = static_cast (0.5) * (mat.coeff (0) + mat.coeff (3)); + typename Matrix::Scalar determinant = mat.coeff (0) * mat.coeff (3) - mat.coeff (1) * mat.coeff (1); + + typename Matrix::Scalar temp = trace * trace - determinant; + + if (temp < 0) + temp = 0; + else + temp = ::std::sqrt (temp); + + eigenvalues.coeffRef (0) = trace - temp; + eigenvalues.coeffRef (1) = trace + temp; + + // either this is in a row or column depending on RowMajor or ColumnMajor + eigenvectors.coeffRef (0) = -mat.coeff (1); + eigenvectors.coeffRef (2) = mat.coeff (0) - eigenvalues.coeff (0); + typename Matrix::Scalar norm = static_cast (1.0) + / static_cast (::std::sqrt (eigenvectors.coeffRef (0) * eigenvectors.coeffRef (0) + eigenvectors.coeffRef (2) * eigenvectors.coeffRef (2))); + eigenvectors.coeffRef (0) *= norm; + eigenvectors.coeffRef (2) *= norm; + eigenvectors.coeffRef (1) = eigenvectors.coeffRef (2); + eigenvectors.coeffRef (3) = -eigenvectors.coeffRef (0); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::computeCorrespondingEigenVector (const Matrix& mat, const typename Matrix::Scalar& eigenvalue, Vector& eigenvector) +{ + typedef typename Matrix::Scalar Scalar; + // Scale the matrix so its entries are in [-1,1]. The scaling is applied + // only when at least one matrix entry has magnitude larger than 1. + + Scalar scale = mat.cwiseAbs ().maxCoeff (); + if (scale <= std::numeric_limits < Scalar > ::min ()) + scale = Scalar (1.0); + + Matrix scaledMat = mat / scale; + + scaledMat.diagonal ().array () -= eigenvalue / scale; + + Vector vec1 = scaledMat.row (0).cross (scaledMat.row (1)); + Vector vec2 = scaledMat.row (0).cross (scaledMat.row (2)); + Vector vec3 = scaledMat.row (1).cross (scaledMat.row (2)); + + Scalar len1 = vec1.squaredNorm (); + Scalar len2 = vec2.squaredNorm (); + Scalar len3 = vec3.squaredNorm (); + + if (len1 >= len2 && len1 >= len3) + eigenvector = vec1 / std::sqrt (len1); + else if (len2 >= len1 && len2 >= len3) + eigenvector = vec2 / std::sqrt (len2); + else + eigenvector = vec3 / std::sqrt (len3); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::eigen33 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenvector) +{ + typedef typename Matrix::Scalar Scalar; + // Scale the matrix so its entries are in [-1,1]. The scaling is applied + // only when at least one matrix entry has magnitude larger than 1. + + Scalar scale = mat.cwiseAbs ().maxCoeff (); + if (scale <= std::numeric_limits < Scalar > ::min ()) + scale = Scalar (1.0); + + Matrix scaledMat = mat / scale; + + Vector eigenvalues; + computeRoots (scaledMat, eigenvalues); + + eigenvalue = eigenvalues (0) * scale; + + scaledMat.diagonal ().array () -= eigenvalues (0); + + Vector vec1 = scaledMat.row (0).cross (scaledMat.row (1)); + Vector vec2 = scaledMat.row (0).cross (scaledMat.row (2)); + Vector vec3 = scaledMat.row (1).cross (scaledMat.row (2)); + + Scalar len1 = vec1.squaredNorm (); + Scalar len2 = vec2.squaredNorm (); + Scalar len3 = vec3.squaredNorm (); + + if (len1 >= len2 && len1 >= len3) + eigenvector = vec1 / std::sqrt (len1); + else if (len2 >= len1 && len2 >= len3) + eigenvector = vec2 / std::sqrt (len2); + else + eigenvector = vec3 / std::sqrt (len3); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::eigen33 (const Matrix& mat, Vector& evals) +{ + typedef typename Matrix::Scalar Scalar; + Scalar scale = mat.cwiseAbs ().maxCoeff (); + if (scale <= std::numeric_limits < Scalar > ::min ()) + scale = Scalar (1.0); + + Matrix scaledMat = mat / scale; + computeRoots (scaledMat, evals); + evals *= scale; +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline void +pcl::eigen33 (const Matrix& mat, Matrix& evecs, Vector& evals) +{ + typedef typename Matrix::Scalar Scalar; + // Scale the matrix so its entries are in [-1,1]. The scaling is applied + // only when at least one matrix entry has magnitude larger than 1. + + Scalar scale = mat.cwiseAbs ().maxCoeff (); + if (scale <= std::numeric_limits < Scalar > ::min ()) + scale = Scalar (1.0); + + Matrix scaledMat = mat / scale; + + // Compute the eigenvalues + computeRoots (scaledMat, evals); + + if ( (evals (2) - evals (0)) <= Eigen::NumTraits < Scalar > ::epsilon ()) + { + // all three equal + evecs.setIdentity (); + } + else if ( (evals (1) - evals (0)) <= Eigen::NumTraits < Scalar > ::epsilon ()) + { + // first and second equal + Matrix tmp; + tmp = scaledMat; + tmp.diagonal ().array () -= evals (2); + + Vector vec1 = tmp.row (0).cross (tmp.row (1)); + Vector vec2 = tmp.row (0).cross (tmp.row (2)); + Vector vec3 = tmp.row (1).cross (tmp.row (2)); + + Scalar len1 = vec1.squaredNorm (); + Scalar len2 = vec2.squaredNorm (); + Scalar len3 = vec3.squaredNorm (); + + if (len1 >= len2 && len1 >= len3) + evecs.col (2) = vec1 / std::sqrt (len1); + else if (len2 >= len1 && len2 >= len3) + evecs.col (2) = vec2 / std::sqrt (len2); + else + evecs.col (2) = vec3 / std::sqrt (len3); + + evecs.col (1) = evecs.col (2).unitOrthogonal (); + evecs.col (0) = evecs.col (1).cross (evecs.col (2)); + } + else if ( (evals (2) - evals (1)) <= Eigen::NumTraits < Scalar > ::epsilon ()) + { + // second and third equal + Matrix tmp; + tmp = scaledMat; + tmp.diagonal ().array () -= evals (0); + + Vector vec1 = tmp.row (0).cross (tmp.row (1)); + Vector vec2 = tmp.row (0).cross (tmp.row (2)); + Vector vec3 = tmp.row (1).cross (tmp.row (2)); + + Scalar len1 = vec1.squaredNorm (); + Scalar len2 = vec2.squaredNorm (); + Scalar len3 = vec3.squaredNorm (); + + if (len1 >= len2 && len1 >= len3) + evecs.col (0) = vec1 / std::sqrt (len1); + else if (len2 >= len1 && len2 >= len3) + evecs.col (0) = vec2 / std::sqrt (len2); + else + evecs.col (0) = vec3 / std::sqrt (len3); + + evecs.col (1) = evecs.col (0).unitOrthogonal (); + evecs.col (2) = evecs.col (0).cross (evecs.col (1)); + } + else + { + Matrix tmp; + tmp = scaledMat; + tmp.diagonal ().array () -= evals (2); + + Vector vec1 = tmp.row (0).cross (tmp.row (1)); + Vector vec2 = tmp.row (0).cross (tmp.row (2)); + Vector vec3 = tmp.row (1).cross (tmp.row (2)); + + Scalar len1 = vec1.squaredNorm (); + Scalar len2 = vec2.squaredNorm (); + Scalar len3 = vec3.squaredNorm (); +#ifdef _WIN32 + Scalar *mmax = new Scalar[3]; +#else + Scalar mmax[3]; +#endif + unsigned int min_el = 2; + unsigned int max_el = 2; + if (len1 >= len2 && len1 >= len3) + { + mmax[2] = len1; + evecs.col (2) = vec1 / std::sqrt (len1); + } + else if (len2 >= len1 && len2 >= len3) + { + mmax[2] = len2; + evecs.col (2) = vec2 / std::sqrt (len2); + } + else + { + mmax[2] = len3; + evecs.col (2) = vec3 / std::sqrt (len3); + } + + tmp = scaledMat; + tmp.diagonal ().array () -= evals (1); + + vec1 = tmp.row (0).cross (tmp.row (1)); + vec2 = tmp.row (0).cross (tmp.row (2)); + vec3 = tmp.row (1).cross (tmp.row (2)); + + len1 = vec1.squaredNorm (); + len2 = vec2.squaredNorm (); + len3 = vec3.squaredNorm (); + if (len1 >= len2 && len1 >= len3) + { + mmax[1] = len1; + evecs.col (1) = vec1 / std::sqrt (len1); + min_el = len1 <= mmax[min_el] ? 1 : min_el; + max_el = len1 > mmax[max_el] ? 1 : max_el; + } + else if (len2 >= len1 && len2 >= len3) + { + mmax[1] = len2; + evecs.col (1) = vec2 / std::sqrt (len2); + min_el = len2 <= mmax[min_el] ? 1 : min_el; + max_el = len2 > mmax[max_el] ? 1 : max_el; + } + else + { + mmax[1] = len3; + evecs.col (1) = vec3 / std::sqrt (len3); + min_el = len3 <= mmax[min_el] ? 1 : min_el; + max_el = len3 > mmax[max_el] ? 1 : max_el; + } + + tmp = scaledMat; + tmp.diagonal ().array () -= evals (0); + + vec1 = tmp.row (0).cross (tmp.row (1)); + vec2 = tmp.row (0).cross (tmp.row (2)); + vec3 = tmp.row (1).cross (tmp.row (2)); + + len1 = vec1.squaredNorm (); + len2 = vec2.squaredNorm (); + len3 = vec3.squaredNorm (); + if (len1 >= len2 && len1 >= len3) + { + mmax[0] = len1; + evecs.col (0) = vec1 / std::sqrt (len1); + min_el = len3 <= mmax[min_el] ? 0 : min_el; + max_el = len3 > mmax[max_el] ? 0 : max_el; + } + else if (len2 >= len1 && len2 >= len3) + { + mmax[0] = len2; + evecs.col (0) = vec2 / std::sqrt (len2); + min_el = len3 <= mmax[min_el] ? 0 : min_el; + max_el = len3 > mmax[max_el] ? 0 : max_el; + } + else + { + mmax[0] = len3; + evecs.col (0) = vec3 / std::sqrt (len3); + min_el = len3 <= mmax[min_el] ? 0 : min_el; + max_el = len3 > mmax[max_el] ? 0 : max_el; + } + + unsigned mid_el = 3 - min_el - max_el; + evecs.col (min_el) = evecs.col ( (min_el + 1) % 3).cross (evecs.col ( (min_el + 2) % 3)).normalized (); + evecs.col (mid_el) = evecs.col ( (mid_el + 1) % 3).cross (evecs.col ( (mid_el + 2) % 3)).normalized (); +#ifdef _WIN32 + delete [] mmax; +#endif + } + // Rescale back to the original size. + evals *= scale; +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline typename Matrix::Scalar +pcl::invert2x2 (const Matrix& matrix, Matrix& inverse) +{ + typedef typename Matrix::Scalar Scalar; + Scalar det = matrix.coeff (0) * matrix.coeff (3) - matrix.coeff (1) * matrix.coeff (2); + + if (det != 0) + { + //Scalar inv_det = Scalar (1.0) / det; + inverse.coeffRef (0) = matrix.coeff (3); + inverse.coeffRef (1) = -matrix.coeff (1); + inverse.coeffRef (2) = -matrix.coeff (2); + inverse.coeffRef (3) = matrix.coeff (0); + inverse /= det; + } + return det; +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline typename Matrix::Scalar +pcl::invert3x3SymMatrix (const Matrix& matrix, Matrix& inverse) +{ + typedef typename Matrix::Scalar Scalar; + // elements + // a b c + // b d e + // c e f + //| a b c |-1 | fd-ee ce-bf be-cd | + //| b d e | = 1/det * | ce-bf af-cc bc-ae | + //| c e f | | be-cd bc-ae ad-bb | + + //det = a(fd-ee) + b(ec-fb) + c(eb-dc) + + Scalar fd_ee = matrix.coeff (4) * matrix.coeff (8) - matrix.coeff (7) * matrix.coeff (5); + Scalar ce_bf = matrix.coeff (2) * matrix.coeff (5) - matrix.coeff (1) * matrix.coeff (8); + Scalar be_cd = matrix.coeff (1) * matrix.coeff (5) - matrix.coeff (2) * matrix.coeff (4); + + Scalar det = matrix.coeff (0) * fd_ee + matrix.coeff (1) * ce_bf + matrix.coeff (2) * be_cd; + + if (det != 0) + { + //Scalar inv_det = Scalar (1.0) / det; + inverse.coeffRef (0) = fd_ee; + inverse.coeffRef (1) = inverse.coeffRef (3) = ce_bf; + inverse.coeffRef (2) = inverse.coeffRef (6) = be_cd; + inverse.coeffRef (4) = (matrix.coeff (0) * matrix.coeff (8) - matrix.coeff (2) * matrix.coeff (2)); + inverse.coeffRef (5) = inverse.coeffRef (7) = (matrix.coeff (1) * matrix.coeff (2) - matrix.coeff (0) * matrix.coeff (5)); + inverse.coeffRef (8) = (matrix.coeff (0) * matrix.coeff (4) - matrix.coeff (1) * matrix.coeff (1)); + inverse /= det; + } + return det; +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline typename Matrix::Scalar +pcl::invert3x3Matrix (const Matrix& matrix, Matrix& inverse) +{ + typedef typename Matrix::Scalar Scalar; + + //| a b c |-1 | ie-hf hc-ib fb-ec | + //| d e f | = 1/det * | gf-id ia-gc dc-fa | + //| g h i | | hd-ge gb-ha ea-db | + //det = a(ie-hf) + d(hc-ib) + g(fb-ec) + + Scalar ie_hf = matrix.coeff (8) * matrix.coeff (4) - matrix.coeff (7) * matrix.coeff (5); + Scalar hc_ib = matrix.coeff (7) * matrix.coeff (2) - matrix.coeff (8) * matrix.coeff (1); + Scalar fb_ec = matrix.coeff (5) * matrix.coeff (1) - matrix.coeff (4) * matrix.coeff (2); + Scalar det = matrix.coeff (0) * (ie_hf) + matrix.coeff (3) * (hc_ib) + matrix.coeff (6) * (fb_ec); + + if (det != 0) + { + inverse.coeffRef (0) = ie_hf; + inverse.coeffRef (1) = hc_ib; + inverse.coeffRef (2) = fb_ec; + inverse.coeffRef (3) = matrix.coeff (6) * matrix.coeff (5) - matrix.coeff (8) * matrix.coeff (3); + inverse.coeffRef (4) = matrix.coeff (8) * matrix.coeff (0) - matrix.coeff (6) * matrix.coeff (2); + inverse.coeffRef (5) = matrix.coeff (3) * matrix.coeff (2) - matrix.coeff (5) * matrix.coeff (0); + inverse.coeffRef (6) = matrix.coeff (7) * matrix.coeff (3) - matrix.coeff (6) * matrix.coeff (4); + inverse.coeffRef (7) = matrix.coeff (6) * matrix.coeff (1) - matrix.coeff (7) * matrix.coeff (0); + inverse.coeffRef (8) = matrix.coeff (4) * matrix.coeff (0) - matrix.coeff (3) * matrix.coeff (1); + + inverse /= det; + } + return det; +} + +////////////////////////////////////////////////////////////////////////////////////////// +template inline typename Matrix::Scalar +pcl::determinant3x3Matrix (const Matrix& matrix) +{ + // result is independent of Row/Col Major storage! + return matrix.coeff (0) * (matrix.coeff (4) * matrix.coeff (8) - matrix.coeff (5) * matrix.coeff (7)) + + matrix.coeff (1) * (matrix.coeff (5) * matrix.coeff (6) - matrix.coeff (3) * matrix.coeff (8)) + + matrix.coeff (2) * (matrix.coeff (3) * matrix.coeff (7) - matrix.coeff (4) * matrix.coeff (6)) ; +} ////////////////////////////////////////////////////////////////////////////////////////// void @@ -124,26 +660,26 @@ pcl::getTransformationFromTwoUnitVectorsAndOrigin (const Eigen::Vector3f& y_dire } ////////////////////////////////////////////////////////////////////////////////////////// -void -pcl::getEulerAngles (const Eigen::Affine3f& t, float& roll, float& pitch, float& yaw) +template void +pcl::getEulerAngles (const Eigen::Transform &t, Scalar &roll, Scalar &pitch, Scalar &yaw) { - roll = atan2f(t(2,1), t(2,2)); - pitch = asinf(-t(2,0)); - yaw = atan2f(t(1,0), t(0,0)); + roll = atan2 (t (2, 1), t (2, 2)); + pitch = asin (-t (2, 0)); + yaw = atan2 (t (1, 0), t (0, 0)); } ////////////////////////////////////////////////////////////////////////////////////////// -void -pcl::getTranslationAndEulerAngles (const Eigen::Affine3f& t, - float& x, float& y, float& z, - float& roll, float& pitch, float& yaw) +template void +pcl::getTranslationAndEulerAngles (const Eigen::Transform &t, + Scalar &x, Scalar &y, Scalar &z, + Scalar &roll, Scalar &pitch, Scalar &yaw) { - x = t(0,3); - y = t(1,3); - z = t(2,3); - roll = atan2f(t(2,1), t(2,2)); - pitch = asinf(-t(2,0)); - yaw = atan2f(t(1,0), t(0,0)); + x = t (0, 3); + y = t (1, 3); + z = t (2, 3); + roll = atan2 (t (2, 1), t (2, 2)); + pitch = asin (-t (2, 0)); + yaw = atan2 (t (1, 0), t (0, 0)); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -161,15 +697,6 @@ pcl::getTransformation (Scalar x, Scalar y, Scalar z, t (3, 0) = 0; t (3, 1) = 0; t (3, 2) = 0; t (3, 3) = 1; } -////////////////////////////////////////////////////////////////////////////////////////// -Eigen::Affine3f -pcl::getTransformation (float x, float y, float z, float roll, float pitch, float yaw) -{ - Eigen::Affine3f t; - getTransformation (x, y, z, roll, pitch, yaw, t); - return (t); -} - ////////////////////////////////////////////////////////////////////////////////////////// template void pcl::saveBinary (const Eigen::MatrixBase& matrix, std::ostream& file) @@ -299,5 +826,176 @@ pcl::umeyama (const Eigen::MatrixBase& src, const Eigen::MatrixBase bool +pcl::transformLine (const Eigen::Matrix &line_in, + Eigen::Matrix &line_out, + const Eigen::Transform &transformation) +{ + if (line_in.innerSize () != 6 || line_out.innerSize () != 6) + { + PCL_DEBUG ("transformLine: lines size != 6\n"); + return (false); + } + + Eigen::Matrix point, vector; + point << line_in.template head<3> (); + vector << line_out.template tail<3> (); + + pcl::transformPoint (point, point, transformation); + pcl::transformVector (vector, vector, transformation); + line_out << point, vector; + return (true); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template void +pcl::transformPlane (const Eigen::Matrix &plane_in, + Eigen::Matrix &plane_out, + const Eigen::Transform &transformation) +{ + Eigen::Hyperplane < Scalar, 3 > plane; + plane.coeffs () << plane_in; + plane.transform (transformation); + plane_out << plane.coeffs (); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template void +pcl::transformPlane (const pcl::ModelCoefficients::Ptr plane_in, + pcl::ModelCoefficients::Ptr plane_out, + const Eigen::Transform &transformation) +{ + Eigen::Matrix < Scalar, 4, 1 > v_plane_in (std::vector < Scalar > (plane_in->values.begin (), plane_in->values.end ()).data ()); + pcl::transformPlane (v_plane_in, v_plane_in, transformation); + plane_out->values.resize (4); + for (int i = 0; i < 4; i++) + plane_in->values[i] = v_plane_in[i]; +} + +////////////////////////////////////////////////////////////////////////////////////////// +template bool +pcl::checkCoordinateSystem (const Eigen::Matrix &line_x, + const Eigen::Matrix &line_y, + const Scalar norm_limit, + const Scalar dot_limit) +{ + if (line_x.innerSize () != 6 || line_y.innerSize () != 6) + { + PCL_DEBUG ("checkCoordinateSystem: lines size != 6\n"); + return (false); + } + + if (line_x.template head<3> () != line_y.template head<3> ()) + { + PCL_DEBUG ("checkCoorZdinateSystem: vector origins are different !\n"); + return (false); + } + + // Make a copy of vector directions + // X^Y = Z | Y^Z = X | Z^X = Y + Eigen::Matrix v_line_x (line_x.template tail<3> ()), + v_line_y (line_y.template tail<3> ()), + v_line_z (v_line_x.cross (v_line_y)); + + // Check vectors norms + if (v_line_x.norm () < 1 - norm_limit || v_line_x.norm () > 1 + norm_limit) + { + PCL_DEBUG ("checkCoordinateSystem: line_x norm %d != 1\n", v_line_x.norm ()); + return (false); + } + + if (v_line_y.norm () < 1 - norm_limit || v_line_y.norm () > 1 + norm_limit) + { + PCL_DEBUG ("checkCoordinateSystem: line_y norm %d != 1\n", v_line_y.norm ()); + return (false); + } + + if (v_line_z.norm () < 1 - norm_limit || v_line_z.norm () > 1 + norm_limit) + { + PCL_DEBUG ("checkCoordinateSystem: line_z norm %d != 1\n", v_line_z.norm ()); + return (false); + } + + // Check vectors perendicularity + if (std::abs (v_line_x.dot (v_line_y)) > dot_limit) + { + PCL_DEBUG ("checkCSAxis: line_x dot line_y %e = > %e\n", v_line_x.dot (v_line_y), dot_limit); + return (false); + } + + if (std::abs (v_line_x.dot (v_line_z)) > dot_limit) + { + PCL_DEBUG ("checkCSAxis: line_x dot line_z = %e > %e\n", v_line_x.dot (v_line_z), dot_limit); + return (false); + } + + if (std::abs (v_line_y.dot (v_line_z)) > dot_limit) + { + PCL_DEBUG ("checkCSAxis: line_y dot line_z = %e > %e\n", v_line_y.dot (v_line_z), dot_limit); + return (false); + } + + return (true); +} + +////////////////////////////////////////////////////////////////////////////////////////// +template bool +pcl::transformBetween2CoordinateSystems (const Eigen::Matrix from_line_x, + const Eigen::Matrix from_line_y, + const Eigen::Matrix to_line_x, + const Eigen::Matrix to_line_y, + Eigen::Transform &transformation) +{ + if (from_line_x.innerSize () != 6 || from_line_y.innerSize () != 6 || to_line_x.innerSize () != 6 || to_line_y.innerSize () != 6) + { + PCL_DEBUG ("transformBetween2CoordinateSystems: lines size != 6\n"); + return (false); + } + + // Check if coordinate systems are valid + if (!pcl::checkCoordinateSystem (from_line_x, from_line_y) || !pcl::checkCoordinateSystem (to_line_x, to_line_y)) + { + PCL_DEBUG ("transformBetween2CoordinateSystems: coordinate systems invalid !\n"); + return (false); + } + + // Convert lines into Vector3 : + Eigen::Matrix fr0 (from_line_x.template head<3>()), + fr1 (from_line_x.template head<3>() + from_line_x.template tail<3>()), + fr2 (from_line_y.template head<3>() + from_line_y.template tail<3>()), + + to0 (to_line_x.template head<3>()), + to1 (to_line_x.template head<3>() + to_line_x.template tail<3>()), + to2 (to_line_y.template head<3>() + to_line_y.template tail<3>()); + + // Code is inspired from http://stackoverflow.com/a/15277421/1816078 + // Define matrices and points : + Eigen::Transform T2, T3 = Eigen::Transform::Identity (); + Eigen::Matrix x1, y1, z1, x2, y2, z2; + + // Axes of the coordinate system "fr" + x1 = (fr1 - fr0).normalized (); // the versor (unitary vector) of the (fr1-fr0) axis vector + y1 = (fr2 - fr0).normalized (); + + // Axes of the coordinate system "to" + x2 = (to1 - to0).normalized (); + y2 = (to2 - to0).normalized (); + + // Transform from CS1 to CS2 + // Note: if fr0 == (0,0,0) --> CS1 == CS2 --> T2 = Identity + T2.linear () << x1, y1, x1.cross (y1); + + // Transform from CS1 to CS3 + T3.linear () << x2, y2, x2.cross (y2); + + // Identity matrix = transform to CS2 to CS3 + // Note: if CS1 == CS2 --> transformation = T3 + transformation = Eigen::Transform::Identity (); + transformation.linear () = T3.linear () * T2.linear ().inverse (); + transformation.translation () = to0 - (transformation.linear () * fr0); + return (true); +} + #endif //PCL_COMMON_EIGEN_IMPL_HPP_ diff --git a/common/include/pcl/common/impl/intersections.hpp b/common/include/pcl/common/impl/intersections.hpp new file mode 100644 index 00000000..619a888e --- /dev/null +++ b/common/include/pcl/common/impl/intersections.hpp @@ -0,0 +1,172 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2010, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + * + */ + +#ifndef PCL_COMMON_INTERSECTIONS_IMPL_HPP_ +#define PCL_COMMON_INTERSECTIONS_IMPL_HPP_ + +#include +#include + +////////////////////////////////////////////////////////////////////////////////////////// + +bool +pcl::lineWithLineIntersection (const Eigen::VectorXf &line_a, + const Eigen::VectorXf &line_b, + Eigen::Vector4f &point, double sqr_eps) +{ + Eigen::Vector4f p1, p2; + lineToLineSegment (line_a, line_b, p1, p2); + + // If the segment size is smaller than a pre-given epsilon... + double sqr_dist = (p1 - p2).squaredNorm (); + if (sqr_dist < sqr_eps) + { + point = p1; + return (true); + } + point.setZero (); + return (false); +} + +bool +pcl::lineWithLineIntersection (const pcl::ModelCoefficients &line_a, + const pcl::ModelCoefficients &line_b, + Eigen::Vector4f &point, double sqr_eps) +{ + Eigen::VectorXf coeff1 = Eigen::VectorXf::Map (&line_a.values[0], line_a.values.size ()); + Eigen::VectorXf coeff2 = Eigen::VectorXf::Map (&line_b.values[0], line_b.values.size ()); + return (lineWithLineIntersection (coeff1, coeff2, point, sqr_eps)); +} + +template bool +pcl::planeWithPlaneIntersection (const Eigen::Matrix &plane_a, + const Eigen::Matrix &plane_b, + Eigen::Matrix &line, + double angular_tolerance) +{ + typedef Eigen::Matrix Vector3; + typedef Eigen::Matrix Vector4; + typedef Eigen::Matrix Vector5; + typedef Eigen::Matrix Matrix5; + + // Normalize plane normals + Vector3 plane_a_norm (plane_a.template head<3> ()); + Vector3 plane_b_norm (plane_b.template head<3> ()); + plane_a_norm.normalize (); + plane_b_norm.normalize (); + + // Test if planes are parallel (test_cos == 1) + double test_cos = plane_a_norm.dot (plane_b_norm); + double upper_limit = 1 + angular_tolerance; + double lower_limit = 1 - angular_tolerance; + + if ((test_cos > lower_limit) && (test_cos < upper_limit)) + { + PCL_DEBUG ("Plane A and Plane B are parallel.\n"); + return (false); + } + + Vector4 line_direction = plane_a.cross3 (plane_b); + line_direction.normalized(); + + // Construct system of equations using lagrange multipliers with one objective function and two constraints + Matrix5 langrange_coefs; + langrange_coefs << 2,0,0, plane_a[0], plane_b[0], + 0,2,0, plane_a[1], plane_b[1], + 0,0,2, plane_a[2], plane_b[2], + plane_a[0], plane_a[1], plane_a[2], 0, 0, + plane_b[0], plane_b[1], plane_b[2], 0, 0; + + Vector5 b; + b << 0, 0, 0, -plane_a[3], -plane_b[3]; + + line.resize(6); + // Solve for the lagrange multipliers + line.template head<3>() = langrange_coefs.colPivHouseholderQr().solve(b).template head<3> (); + line.template tail<3>() = line_direction.template head<3>(); + return (true); +} + +template bool +pcl::threePlanesIntersection (const Eigen::Matrix &plane_a, + const Eigen::Matrix &plane_b, + const Eigen::Matrix &plane_c, + Eigen::Matrix &intersection_point, + double determinant_tolerance) +{ + typedef Eigen::Matrix Vector3; + typedef Eigen::Matrix Matrix3; + + // TODO: Using Eigen::HyperPlanes is better to solve this problem + // Check if some planes are parallel + Matrix3 normals_in_lines; + + for (int i = 0; i < 3; i++) + { + normals_in_lines (i, 0) = plane_a[i]; + normals_in_lines (i, 1) = plane_b[i]; + normals_in_lines (i, 2) = plane_c[i]; + } + + Scalar determinant = normals_in_lines.determinant (); + if (fabs (determinant) < determinant_tolerance) + { + // det ~= 0 + PCL_DEBUG ("At least two planes are parralel.\n"); + return (false); + } + + // Left part of the 3 equations + Matrix3 left_member; + + for (int i = 0; i < 3; i++) + { + left_member (0, i) = plane_a[i]; + left_member (1, i) = plane_b[i]; + left_member (2, i) = plane_c[i]; + } + + // Right side of the 3 equations + Vector3 right_member; + right_member << -plane_a[3], -plane_b[3], -plane_c[3]; + + // Solve the system + intersection_point = left_member.fullPivLu ().solve (right_member); + return (true); +} + +#endif //PCL_COMMON_INTERSECTIONS_IMPL_HPP diff --git a/common/include/pcl/common/impl/io.hpp b/common/include/pcl/common/impl/io.hpp index 3d40c718..9ddd7797 100644 --- a/common/include/pcl/common/impl/io.hpp +++ b/common/include/pcl/common/impl/io.hpp @@ -42,6 +42,7 @@ #define PCL_IO_IMPL_IO_HPP_ #include +#include #include ////////////////////////////////////////////////////////////////////////////////////////////// @@ -107,14 +108,10 @@ pcl::getFieldsList (const pcl::PointCloud &) ////////////////////////////////////////////////////////////////////////////////////////////// template void -pcl::copyPointCloud (const pcl::PointCloud &cloud_in, +pcl::copyPointCloud (const pcl::PointCloud &cloud_in, pcl::PointCloud &cloud_out) { - // Copy all the data fields from the input cloud to the output one - typedef typename pcl::traits::fieldList::type FieldListInT; - typedef typename pcl::traits::fieldList::type FieldListOutT; - typedef typename pcl::intersect::type FieldList; - + // Allocate enough space and copy the basics cloud_out.header = cloud_in.header; cloud_out.width = cloud_in.width; cloud_out.height = cloud_in.height; @@ -123,57 +120,13 @@ pcl::copyPointCloud (const pcl::PointCloud &cloud_in, cloud_out.sensor_origin_ = cloud_in.sensor_origin_; cloud_out.points.resize (cloud_in.points.size ()); - // If the point types are the same, don't copy one by one if (isSamePointType ()) - { + // Copy the whole memory block memcpy (&cloud_out.points[0], &cloud_in.points[0], cloud_in.points.size () * sizeof (PointInT)); - return; - } - - std::vector fields_in, fields_out; - pcl::for_each_type (pcl::detail::FieldAdder (fields_in)); - pcl::for_each_type (pcl::detail::FieldAdder (fields_out)); - - // RGB vs RGBA is an official missmatch until PCL 2.0, so we need to search for it and - // fix it manually - int rgb_idx_in = -1, rgb_idx_out = -1; - for (size_t i = 0; i < fields_in.size (); ++i) - if (fields_in[i].name == "rgb" || fields_in[i].name == "rgba") - { - rgb_idx_in = int (i); - break; - } - for (size_t i = 0; i < fields_out.size (); ++i) - if (fields_out[i].name == "rgb" || fields_out[i].name == "rgba") - { - rgb_idx_out = int (i); - break; - } - - // We have one of the two cases: RGB vs RGBA or RGBA vs RGB - if (rgb_idx_in != -1 && rgb_idx_out != -1 && - fields_in[rgb_idx_in].name != fields_out[rgb_idx_out].name) - { - size_t field_size_in = getFieldSize (fields_in[rgb_idx_in].datatype), - field_size_out = getFieldSize (fields_out[rgb_idx_out].datatype); - - if (field_size_in == field_size_out) - { - for (size_t i = 0; i < cloud_in.points.size (); ++i) - { - // Copy the rest - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[i], cloud_out.points[i])); - // Copy RGB<->RGBA - memcpy (reinterpret_cast (&cloud_out.points[i]) + fields_out[rgb_idx_out].offset, reinterpret_cast (&cloud_in.points[i]) + fields_in[rgb_idx_in].offset, field_size_in); - } - return; - } - } - - // Iterate over each point if no RGB/RGBA or if their size is different - for (size_t i = 0; i < cloud_in.points.size (); ++i) - // Iterate over each dimension - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[i], cloud_out.points[i])); + else + // Iterate over each point + for (size_t i = 0; i < cloud_in.points.size (); ++i) + copyPoint (cloud_in.points[i], cloud_out.points[i]); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -232,7 +185,7 @@ pcl::copyPointCloud (const pcl::PointCloud &cloud_in, ////////////////////////////////////////////////////////////////////////////////////////////// template void -pcl::copyPointCloud (const pcl::PointCloud &cloud_in, +pcl::copyPointCloud (const pcl::PointCloud &cloud_in, const std::vector &indices, pcl::PointCloud &cloud_out) { @@ -245,69 +198,14 @@ pcl::copyPointCloud (const pcl::PointCloud &cloud_in, cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_; cloud_out.sensor_origin_ = cloud_in.sensor_origin_; - // Copy all the data fields from the input cloud to the output one - typedef typename pcl::traits::fieldList::type FieldListInT; - typedef typename pcl::traits::fieldList::type FieldListOutT; - typedef typename pcl::intersect::type FieldList; - - // If the point types are the same, don't copy one by one - if (isSamePointType ()) - { - // Iterate over each point - for (size_t i = 0; i < indices.size (); ++i) - memcpy (&cloud_out.points[i], &cloud_in.points[indices[i]], sizeof (PointInT)); - return; - } - - std::vector fields_in, fields_out; - pcl::for_each_type (pcl::detail::FieldAdder (fields_in)); - pcl::for_each_type (pcl::detail::FieldAdder (fields_out)); - - // RGB vs RGBA is an official missmatch until PCL 2.0, so we need to search for it and - // fix it manually - int rgb_idx_in = -1, rgb_idx_out = -1; - for (size_t i = 0; i < fields_in.size (); ++i) - if (fields_in[i].name == "rgb" || fields_in[i].name == "rgba") - { - rgb_idx_in = int (i); - break; - } - for (size_t i = 0; int (i) < fields_out.size (); ++i) - if (fields_out[i].name == "rgb" || fields_out[i].name == "rgba") - { - rgb_idx_out = int (i); - break; - } - - // We have one of the two cases: RGB vs RGBA or RGBA vs RGB - if (rgb_idx_in != -1 && rgb_idx_out != -1 && - fields_in[rgb_idx_in].name != fields_out[rgb_idx_out].name) - { - size_t field_size_in = getFieldSize (fields_in[rgb_idx_in].datatype), - field_size_out = getFieldSize (fields_out[rgb_idx_out].datatype); - - if (field_size_in == field_size_out) - { - for (size_t i = 0; i < indices.size (); ++i) - { - // Copy the rest - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices[i]], cloud_out.points[i])); - // Copy RGB<->RGBA - memcpy (reinterpret_cast (&cloud_out.points[indices[i]]) + fields_out[rgb_idx_out].offset, reinterpret_cast (&cloud_in.points[i]) + fields_in[rgb_idx_in].offset, field_size_in); - } - return; - } - } - - // Iterate over each point if no RGB/RGBA or if their size is different + // Iterate over each point for (size_t i = 0; i < indices.size (); ++i) - // Iterate over each dimension - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices[i]], cloud_out.points[i])); + copyPoint (cloud_in.points[indices[i]], cloud_out.points[i]); } ////////////////////////////////////////////////////////////////////////////////////////////// template void -pcl::copyPointCloud (const pcl::PointCloud &cloud_in, +pcl::copyPointCloud (const pcl::PointCloud &cloud_in, const std::vector > &indices, pcl::PointCloud &cloud_out) { @@ -320,64 +218,9 @@ pcl::copyPointCloud (const pcl::PointCloud &cloud_in, cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_; cloud_out.sensor_origin_ = cloud_in.sensor_origin_; - // Copy all the data fields from the input cloud to the output one - typedef typename pcl::traits::fieldList::type FieldListInT; - typedef typename pcl::traits::fieldList::type FieldListOutT; - typedef typename pcl::intersect::type FieldList; - - // If the point types are the same, don't copy one by one - if (isSamePointType ()) - { - // Iterate over each point - for (size_t i = 0; i < indices.size (); ++i) - memcpy (&cloud_out.points[i], &cloud_in.points[indices[i]], sizeof (PointInT)); - return; - } - - std::vector fields_in, fields_out; - pcl::for_each_type (pcl::detail::FieldAdder (fields_in)); - pcl::for_each_type (pcl::detail::FieldAdder (fields_out)); - - // RGB vs RGBA is an official missmatch until PCL 2.0, so we need to search for it and - // fix it manually - int rgb_idx_in = -1, rgb_idx_out = -1; - for (size_t i = 0; i < fields_in.size (); ++i) - if (fields_in[i].name == "rgb" || fields_in[i].name == "rgba") - { - rgb_idx_in = int (i); - break; - } - for (size_t i = 0; i < fields_out.size (); ++i) - if (fields_out[i].name == "rgb" || fields_out[i].name == "rgba") - { - rgb_idx_out = int (i); - break; - } - - // We have one of the two cases: RGB vs RGBA or RGBA vs RGB - if (rgb_idx_in != -1 && rgb_idx_out != -1 && - fields_in[rgb_idx_in].name != fields_out[rgb_idx_out].name) - { - size_t field_size_in = getFieldSize (fields_in[rgb_idx_in].datatype), - field_size_out = getFieldSize (fields_out[rgb_idx_out].datatype); - - if (field_size_in == field_size_out) - { - for (size_t i = 0; i < indices.size (); ++i) - { - // Copy the rest - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices[i]], cloud_out.points[i])); - // Copy RGB<->RGBA - memcpy (reinterpret_cast (&cloud_out.points[i]) + fields_out[rgb_idx_out].offset, reinterpret_cast (&cloud_in.points[indices[i]]) + fields_in[rgb_idx_in].offset, field_size_in); - } - return; - } - } - - // Iterate over each point if no RGB/RGBA or if their size is different + // Iterate over each point for (size_t i = 0; i < indices.size (); ++i) - // Iterate over each dimension - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices[i]], cloud_out.points[i])); + copyPoint (cloud_in.points[indices[i]], cloud_out.points[i]); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -409,77 +252,11 @@ pcl::copyPointCloud (const pcl::PointCloud &cloud_in, /////////////////////////////////////////////////////////////////////////////////////////////// template void -pcl::copyPointCloud (const pcl::PointCloud &cloud_in, +pcl::copyPointCloud (const pcl::PointCloud &cloud_in, const pcl::PointIndices &indices, pcl::PointCloud &cloud_out) { - // Allocate enough space and copy the basics - cloud_out.points.resize (indices.indices.size ()); - cloud_out.header = cloud_in.header; - cloud_out.width = indices.indices.size (); - cloud_out.height = 1; - cloud_out.is_dense = cloud_in.is_dense; - cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_; - cloud_out.sensor_origin_ = cloud_in.sensor_origin_; - - // Copy all the data fields from the input cloud to the output one - typedef typename pcl::traits::fieldList::type FieldListInT; - typedef typename pcl::traits::fieldList::type FieldListOutT; - typedef typename pcl::intersect::type FieldList; - - // If the point types are the same, don't copy one by one - if (isSamePointType ()) - { - // Iterate over each point - for (size_t i = 0; i < indices.indices.size (); ++i) - memcpy (&cloud_out.points[i], &cloud_in.points[indices.indices[i]], sizeof (PointInT)); - return; - } - - std::vector fields_in, fields_out; - pcl::for_each_type (pcl::detail::FieldAdder (fields_in)); - pcl::for_each_type (pcl::detail::FieldAdder (fields_out)); - - // RGB vs RGBA is an official missmatch until PCL 2.0, so we need to search for it and - // fix it manually - int rgb_idx_in = -1, rgb_idx_out = -1; - for (size_t i = 0; i < fields_in.size (); ++i) - if (fields_in[i].name == "rgb" || fields_in[i].name == "rgba") - { - rgb_idx_in = int (i); - break; - } - for (size_t i = 0; i < fields_out.size (); ++i) - if (fields_out[i].name == "rgb" || fields_out[i].name == "rgba") - { - rgb_idx_out = int (i); - break; - } - - // We have one of the two cases: RGB vs RGBA or RGBA vs RGB - if (rgb_idx_in != -1 && rgb_idx_out != -1 && - fields_in[rgb_idx_in].name != fields_out[rgb_idx_out].name) - { - size_t field_size_in = getFieldSize (fields_in[rgb_idx_in].datatype), - field_size_out = getFieldSize (fields_out[rgb_idx_out].datatype); - - if (field_size_in == field_size_out) - { - for (size_t i = 0; i < indices.indices.size (); ++i) - { - // Copy the rest - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices.indices[i]], cloud_out.points[i])); - // Copy RGB<->RGBA - memcpy (reinterpret_cast (&cloud_out.points[indices.indices[i]]) + fields_out[rgb_idx_out].offset, reinterpret_cast (&cloud_in.points[i]) + fields_in[rgb_idx_in].offset, field_size_in); - } - return; - } - } - - // Iterate over each point if no RGB/RGBA or if their size is different - for (size_t i = 0; i < indices.indices.size (); ++i) - // Iterate over each dimension - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices.indices[i]], cloud_out.points[i])); + copyPointCloud (cloud_in, indices.indices, cloud_out); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -548,75 +325,6 @@ pcl::copyPointCloud (const pcl::PointCloud &cloud_in, cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_; cloud_out.sensor_origin_ = cloud_in.sensor_origin_; - // Copy all the data fields from the input cloud to the output one - typedef typename pcl::traits::fieldList::type FieldListInT; - typedef typename pcl::traits::fieldList::type FieldListOutT; - typedef typename pcl::intersect::type FieldList; - - // If the point types are the same, don't copy one by one - if (isSamePointType ()) - { - // Iterate over each cluster - int cp = 0; - for (size_t cc = 0; cc < indices.size (); ++cc) - { - // Iterate over each idx - for (size_t i = 0; i < indices[cc].indices.size (); ++i) - { - cloud_out.points[cp] = cloud_in.points[indices[cc].indices[i]]; - ++cp; - } - } - return; - } - - std::vector fields_in, fields_out; - pcl::for_each_type (pcl::detail::FieldAdder (fields_in)); - pcl::for_each_type (pcl::detail::FieldAdder (fields_out)); - - // RGB vs RGBA is an official missmatch until PCL 2.0, so we need to search for it and - // fix it manually - int rgb_idx_in = -1, rgb_idx_out = -1; - for (size_t i = 0; i < fields_in.size (); ++i) - if (fields_in[i].name == "rgb" || fields_in[i].name == "rgba") - { - rgb_idx_in = int (i); - break; - } - for (size_t i = 0; i < fields_out.size (); ++i) - if (fields_out[i].name == "rgb" || fields_out[i].name == "rgba") - { - rgb_idx_out = int (i); - break; - } - - // We have one of the two cases: RGB vs RGBA or RGBA vs RGB - if (rgb_idx_in != -1 && rgb_idx_out != -1 && - fields_in[rgb_idx_in].name != fields_out[rgb_idx_out].name) - { - size_t field_size_in = getFieldSize (fields_in[rgb_idx_in].datatype), - field_size_out = getFieldSize (fields_out[rgb_idx_out].datatype); - - if (field_size_in == field_size_out) - { - // Iterate over each cluster - int cp = 0; - for (size_t cc = 0; cc < indices.size (); ++cc) - { - // Iterate over each idx - for (size_t i = 0; i < indices[cc].indices.size (); ++i) - { - // Iterate over each dimension - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices[cc].indices[i]], cloud_out.points[cp])); - // Copy RGB<->RGBA - memcpy (reinterpret_cast (&cloud_out.points[cp]) + fields_out[rgb_idx_out].offset, reinterpret_cast (&cloud_in.points[indices[cp].indices[i]]) + fields_in[rgb_idx_in].offset, field_size_in); - ++cp; - } - } - return; - } - } - // Iterate over each cluster int cp = 0; for (size_t cc = 0; cc < indices.size (); ++cc) @@ -624,8 +332,7 @@ pcl::copyPointCloud (const pcl::PointCloud &cloud_in, // Iterate over each idx for (size_t i = 0; i < indices[cc].indices.size (); ++i) { - // Iterate over each dimension - pcl::for_each_type (pcl::NdConcatenateFunctor (cloud_in.points[indices[cc].indices[i]], cloud_out.points[cp])); + copyPoint (cloud_in.points[indices[cc].indices[i]], cloud_out.points[cp]); ++cp; } } @@ -665,5 +372,131 @@ pcl::concatenateFields (const pcl::PointCloud &cloud1_in, } } +////////////////////////////////////////////////////////////////////////////////////////////// +template void +pcl::copyPointCloud (const pcl::PointCloud &cloud_in, pcl::PointCloud &cloud_out, + int top, int bottom, int left, int right, pcl::InterpolationType border_type, const PointT& value) +{ + if (top < 0 || left < 0 || bottom < 0 || right < 0) + { + std::string faulty = (top < 0) ? "top" : (left < 0) ? "left" : (bottom < 0) ? "bottom" : "right"; + PCL_THROW_EXCEPTION (pcl::BadArgumentException, "[pcl::copyPointCloud] error: " << faulty << " must be positive!"); + return; + } + + if (top == 0 && left == 0 && bottom == 0 && right == 0) + cloud_out = cloud_in; + else + { + // Allocate enough space and copy the basics + cloud_out.header = cloud_in.header; + cloud_out.width = cloud_in.width + left + right; + cloud_out.height = cloud_in.height + top + bottom; + if (cloud_out.size () != cloud_out.width * cloud_out.height) + cloud_out.resize (cloud_out.width * cloud_out.height); + cloud_out.is_dense = cloud_in.is_dense; + cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_; + cloud_out.sensor_origin_ = cloud_in.sensor_origin_; + + if (border_type == pcl::BORDER_TRANSPARENT) + { + const PointT* in = &(cloud_in.points[0]); + PointT* out = &(cloud_out.points[0]); + PointT* out_inner = out + cloud_out.width*top + left; + for (uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width) + { + if (out_inner != in) + memcpy (out_inner, in, cloud_in.width * sizeof (PointT)); + } + } + else + { + // Copy the data + if (border_type != pcl::BORDER_CONSTANT) + { + try + { + std::vector padding (cloud_out.width - cloud_in.width); + int right = cloud_out.width - cloud_in.width - left; + int bottom = cloud_out.height - cloud_in.height - top; + + for (int i = 0; i < left; i++) + padding[i] = pcl::interpolatePointIndex (i-left, cloud_in.width, border_type); + + for (int i = 0; i < right; i++) + padding[i+left] = pcl::interpolatePointIndex (cloud_in.width+i, cloud_in.width, border_type); + + const PointT* in = &(cloud_in.points[0]); + PointT* out = &(cloud_out.points[0]); + PointT* out_inner = out + cloud_out.width*top + left; + + for (uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width) + { + if (out_inner != in) + memcpy (out_inner, in, cloud_in.width * sizeof (PointT)); + + for (int j = 0; j < left; j++) + out_inner[j - left] = in[padding[j]]; + + for (int j = 0; j < right; j++) + out_inner[j + cloud_in.width] = in[padding[j + left]]; + } + + for (int i = 0; i < top; i++) + { + int j = pcl::interpolatePointIndex (i - top, cloud_in.height, border_type); + memcpy (out + i*cloud_out.width, + out + (j+top) * cloud_out.width, + sizeof (PointT) * cloud_out.width); + } + + for (int i = 0; i < bottom; i++) + { + int j = pcl::interpolatePointIndex (i + cloud_in.height, cloud_in.height, border_type); + memcpy (out + (i + cloud_in.height + top)*cloud_out.width, + out + (j+top)*cloud_out.width, + cloud_out.width * sizeof (PointT)); + } + } + catch (pcl::BadArgumentException &e) + { + PCL_ERROR ("[pcl::copyPointCloud] Unhandled interpolation type %d!\n", border_type); + } + } + else + { + int right = cloud_out.width - cloud_in.width - left; + int bottom = cloud_out.height - cloud_in.height - top; + std::vector buff (cloud_out.width, value); + PointT* buff_ptr = &(buff[0]); + const PointT* in = &(cloud_in.points[0]); + PointT* out = &(cloud_out.points[0]); + PointT* out_inner = out + cloud_out.width*top + left; + + for (uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width) + { + if (out_inner != in) + memcpy (out_inner, in, cloud_in.width * sizeof (PointT)); + + memcpy (out_inner - left, buff_ptr, left * sizeof (PointT)); + memcpy (out_inner + cloud_in.width, buff_ptr, right * sizeof (PointT)); + } + + for (int i = 0; i < top; i++) + { + memcpy (out + i*cloud_out.width, buff_ptr, cloud_out.width * sizeof (PointT)); + } + + for (int i = 0; i < bottom; i++) + { + memcpy (out + (i + cloud_in.height + top)*cloud_out.width, + buff_ptr, + cloud_out.width * sizeof (PointT)); + } + } + } + } +} + #endif // PCL_IO_IMPL_IO_H_ diff --git a/common/include/pcl/common/impl/pca.hpp b/common/include/pcl/common/impl/pca.hpp index b274f5c0..68d5b61c 100644 --- a/common/include/pcl/common/impl/pca.hpp +++ b/common/include/pcl/common/impl/pca.hpp @@ -47,15 +47,15 @@ ///////////////////////////////////////////////////////////////////////////////////////// /** \brief Constructor with direct computation - * \param[in] X input m*n matrix (ie n vectors of R(m)) + * \param[in] cloud input m*n matrix (ie n vectors of R(m)) * \param[in] basis_only flag to compute only the PCA basis */ template -pcl::PCA::PCA (const pcl::PointCloud& X, bool basis_only) +pcl::PCA::PCA (const pcl::PointCloud &cloud, bool basis_only) { Base (); basis_only_ = basis_only; - setInputCloud (X.makeShared ()); + setInputCloud (cloud.makeShared ()); compute_done_ = initCompute (); } diff --git a/common/include/pcl/common/intensity.h b/common/include/pcl/common/intensity.h index 33f0baab..673cfe1e 100644 --- a/common/include/pcl/common/intensity.h +++ b/common/include/pcl/common/intensity.h @@ -51,7 +51,7 @@ namespace pcl struct IntensityFieldAccessor { /** \brief get intensity field - * \param[in] point p + * \param[in] p point * \return p.intensity */ inline float @@ -60,7 +60,7 @@ namespace pcl return p.intensity; } /** \brief gets the intensity value of a point - * \param[in/out] p point for which intensity to be get + * \param p point for which intensity to be get * \param[in] intensity value of the intensity field */ inline void @@ -69,7 +69,7 @@ namespace pcl intensity = p.intensity; } /** \brief sets the intensity value of a point - * \param[in/out] p point for which intensity to be set + * \param p point for which intensity to be set * \param[in] intensity value of the intensity field */ inline void @@ -78,7 +78,7 @@ namespace pcl p.intensity = intensity; } /** \brief subtract value from intensity field - * \param[in/out] p point for which to modify inetnsity + * \param p point for which to modify inetnsity * \param[in] value value to be subtracted from point intensity */ inline void @@ -87,7 +87,7 @@ namespace pcl p.intensity -= value; } /** \brief add value to intensity field - * \param[in/out] p point for which to modify inetnsity + * \param p point for which to modify inetnsity * \param[in] value value to be added to point intensity */ inline void diff --git a/common/include/pcl/common/intersections.h b/common/include/pcl/common/intersections.h index fb81d36e..7cf30b12 100644 --- a/common/include/pcl/common/intersections.h +++ b/common/include/pcl/common/intersections.h @@ -34,6 +34,7 @@ * $Id$ * */ + #ifndef PCL_INTERSECTIONS_H_ #define PCL_INTERSECTIONS_H_ @@ -57,10 +58,11 @@ namespace pcl * \param[in] sqr_eps maximum allowable squared distance to the true solution * \ingroup common */ - PCL_EXPORTS bool + PCL_EXPORTS inline bool lineWithLineIntersection (const Eigen::VectorXf &line_a, const Eigen::VectorXf &line_b, - Eigen::Vector4f &point, double sqr_eps = 1e-4); + Eigen::Vector4f &point, + double sqr_eps = 1e-4); /** \brief Get the intersection of a two 3D lines in space as a 3D point * \param[in] line_a the coefficients of the first line (point, direction) @@ -69,24 +71,90 @@ namespace pcl * \param[in] sqr_eps maximum allowable squared distance to the true solution * \ingroup common */ - PCL_EXPORTS bool + + PCL_EXPORTS inline bool lineWithLineIntersection (const pcl::ModelCoefficients &line_a, const pcl::ModelCoefficients &line_b, - Eigen::Vector4f &point, double sqr_eps = 1e-4); + Eigen::Vector4f &point, + double sqr_eps = 1e-4); /** \brief Determine the line of intersection of two non-parallel planes using lagrange multipliers * \note Described in: "Intersection of Two Planes, John Krumm, Microsoft Research, Redmond, WA, USA" * \param[in] plane_a coefficients of plane A and plane B in the form ax + by + cz + d = 0 - * \param[out] plane_b coefficients of line where line.tail<3>() = direction vector and + * \param[in] plane_b coefficients of line where line.tail<3>() = direction vector and * line.head<3>() the point on the line clossest to (0, 0, 0) + * \param[out] line the intersected line to be filled + * \param[in] angular_tolerance tolerance in radians * \return true if succeeded/planes aren't parallel */ - PCL_EXPORTS bool + PCL_EXPORTS template bool + planeWithPlaneIntersection (const Eigen::Matrix &plane_a, + const Eigen::Matrix &plane_b, + Eigen::Matrix &line, + double angular_tolerance = 0.1); + + PCL_EXPORTS inline bool planeWithPlaneIntersection (const Eigen::Vector4f &plane_a, - const Eigen::Vector4f &fplane_b, + const Eigen::Vector4f &plane_b, Eigen::VectorXf &line, - double angular_tolerance = 0.1); + double angular_tolerance = 0.1) + { + return (planeWithPlaneIntersection (plane_a, plane_b, line, angular_tolerance)); + } + + PCL_EXPORTS inline bool + planeWithPlaneIntersection (const Eigen::Vector4d &plane_a, + const Eigen::Vector4d &plane_b, + Eigen::VectorXd &line, + double angular_tolerance = 0.1) + { + return (planeWithPlaneIntersection (plane_a, plane_b, line, angular_tolerance)); + } + + /** \brief Determine the point of intersection of three non-parallel planes by solving the equations. + * \note If using nearly parralel planes you can lower the determinant_tolerance value. This can + * lead to inconsistent results. + * If the three planes intersects in a line the point will be anywhere on the line. + * \param[in] plane_a are the coefficients of the first plane in the form ax + by + cz + d = 0 + * \param[in] plane_b are the coefficients of the second plane + * \param[in] plane_c are the coefficients of the third plane + * \param[in] determinant_tolerance is a limit to determine whether planes are parallel or not + * \param[out] intersection_point the three coordinates x, y, z of the intersection point + * \return true if succeeded/planes aren't parallel + */ + PCL_EXPORTS template bool + threePlanesIntersection (const Eigen::Matrix &plane_a, + const Eigen::Matrix &plane_b, + const Eigen::Matrix &plane_c, + Eigen::Matrix &intersection_point, + double determinant_tolerance = 1e-6); + + + PCL_EXPORTS inline bool + threePlanesIntersection (const Eigen::Vector4f &plane_a, + const Eigen::Vector4f &plane_b, + const Eigen::Vector4f &plane_c, + Eigen::Vector3f &intersection_point, + double determinant_tolerance = 1e-6) + { + return (threePlanesIntersection (plane_a, plane_b, plane_c, + intersection_point, determinant_tolerance)); + } + + PCL_EXPORTS inline bool + threePlanesIntersection (const Eigen::Vector4d &plane_a, + const Eigen::Vector4d &plane_b, + const Eigen::Vector4d &plane_c, + Eigen::Vector3d &intersection_point, + double determinant_tolerance = 1e-6) + { + return (threePlanesIntersection (plane_a, plane_b, plane_c, + intersection_point, determinant_tolerance)); + } + } /*@}*/ -#endif //#ifndef PCL_INTERSECTIONS_H_ +#include + +#endif //#ifndef PCL_INTERSECTIONS_H_ diff --git a/common/include/pcl/common/io.h b/common/include/pcl/common/io.h index f2c415ff..ec72feda 100644 --- a/common/include/pcl/common/io.h +++ b/common/include/pcl/common/io.h @@ -45,6 +45,7 @@ #include #include #include +#include #include namespace pcl @@ -223,6 +224,24 @@ namespace pcl } } + typedef enum + { + BORDER_CONSTANT = 0, BORDER_REPLICATE = 1, + BORDER_REFLECT = 2, BORDER_WRAP = 3, + BORDER_REFLECT_101 = 4, BORDER_TRANSPARENT = 5, + BORDER_DEFAULT = BORDER_REFLECT_101 + } InterpolationType; + + /** \brief \return the right index according to the interpolation type. + * \note this is adapted from OpenCV + * \param p the index of point to interpolate + * \param length the top/bottom row or left/right column index + * \param type the requested interpolation + * \throws pcl::BadArgumentException if type is unknown + */ + PCL_EXPORTS int + interpolatePointIndex (int p, int length, InterpolationType type); + /** \brief Concatenate two pcl::PCLPointCloud2. * \param[in] cloud1 the first input point cloud dataset * \param[in] cloud2 the second input point cloud dataset @@ -380,6 +399,31 @@ namespace pcl const std::vector &indices, pcl::PointCloud &cloud_out); + /** \brief Copy a point cloud inside a larger one interpolating borders. + * \param[in] cloud_in the input point cloud dataset + * \param[out] cloud_out the resultant output point cloud dataset + * \param top + * \param bottom + * \param left + * \param right + * Position of cloud_in inside cloud_out is given by \a top, \a left, \a bottom \a right. + * \param[in] border_type the interpolating method (pcl::BORDER_XXX) + * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh + * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb + * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba + * BORDER_WRAP: cdefgh|abcdefgh|abcdefg + * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i' + * BORDER_TRANSPARENT: mnopqr|abcdefgh|tuvwxyz where m-r and t-z are orignal values of cloud_out + * \param value + * \throw pcl::BadArgumentException if any of top, bottom, left or right is negative. + * \ingroup common + */ + template void + copyPointCloud (const pcl::PointCloud &cloud_in, + pcl::PointCloud &cloud_out, + int top, int bottom, int left, int right, + pcl::InterpolationType border_type, const PointT& value); + /** \brief Concatenate two datasets representing different fields. * * \note If the input datasets have overlapping fields (i.e., both contain diff --git a/common/include/pcl/common/pca.h b/common/include/pcl/common/pca.h index a414539d..509cbdc9 100644 --- a/common/include/pcl/common/pca.h +++ b/common/include/pcl/common/pca.h @@ -98,8 +98,8 @@ namespace pcl * X input m*n matrix (ie n vectors of R(m)) * basis_only flag to compute only the PCA basis */ - PCL_DEPRECATED (PCA (const pcl::PointCloud& X, bool basis_only = false), - "Use PCA (bool basis_only); setInputCloud (X.makeShared ()); instead"); + PCL_DEPRECATED ("Use PCA (bool basis_only); setInputCloud (X.makeShared ()); instead") + PCA (const pcl::PointCloud& X, bool basis_only = false); /** Copy Constructor * \param[in] pca PCA object diff --git a/common/include/pcl/common/point_tests.h b/common/include/pcl/common/point_tests.h index 7dbafdaf..f202af7a 100644 --- a/common/include/pcl/common/point_tests.h +++ b/common/include/pcl/common/point_tests.h @@ -66,6 +66,7 @@ namespace pcl template<> inline bool isFinite (const pcl::RGB&) { return (true); } template<> inline bool isFinite (const pcl::Label&) { return (true); } template<> inline bool isFinite (const pcl::Axis&) { return (true); } + template<> inline bool isFinite (const pcl::Intensity&) { return (true); } template<> inline bool isFinite (const pcl::MomentInvariants&) { return (true); } template<> inline bool isFinite (const pcl::PrincipalRadiiRSD&) { return (true); } template<> inline bool isFinite (const pcl::Boundary&) { return (true); } diff --git a/common/include/pcl/common/random.h b/common/include/pcl/common/random.h index 696018d1..da446086 100644 --- a/common/include/pcl/common/random.h +++ b/common/include/pcl/common/random.h @@ -109,7 +109,7 @@ namespace pcl /** Constructor * \param parameters uniform distribution parameters and generator seed */ - UniformGenerator(const Parameters& paramters); + UniformGenerator(const Parameters& parameters); /** Change seed value * \param[in] seed new generator seed value diff --git a/common/include/pcl/console/parse.h b/common/include/pcl/console/parse.h index a4163e9a..00158752 100644 --- a/common/include/pcl/console/parse.h +++ b/common/include/pcl/console/parse.h @@ -62,7 +62,7 @@ namespace pcl * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] argument_name the string value to search for - * \return index of found argument or -1 of arguments does not appear in list + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int find_argument (int argc, char** argv, const char* argument_name); @@ -72,7 +72,7 @@ namespace pcl * \param[in] argv the command line arguments * \param[in] argument_name the name of the argument to search for * \param[out] value The value of the argument - * \return index of found argument or -1 of arguments does not appear in list + * \return index of found argument or -1 if arguments do not appear in list */ template int parse (int argc, char** argv, const char* argument_name, Type& value) @@ -90,114 +90,117 @@ namespace pcl return (index - 1); } - /** \brief Parse for a specific given command line argument. Returns the value - * sent as a string. + /** \brief Parse for a specific given command line argument. * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] val the resultant value + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_argument (int argc, char** argv, const char* str, std::string &val); - /** \brief Parse for a specific given command line argument. Returns the value - * sent as a boolean. + /** \brief Parse for a specific given command line argument. * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] val the resultant value + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_argument (int argc, char** argv, const char* str, bool &val); - /** \brief Parse for a specific given command line argument. Returns the value - * sent as a double. + /** \brief Parse for a specific given command line argument. * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] val the resultant value + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_argument (int argc, char** argv, const char* str, float &val); - /** \brief Parse for a specific given command line argument. Returns the value - * sent as a double. + /** \brief Parse for a specific given command line argument. * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] val the resultant value + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_argument (int argc, char** argv, const char* str, double &val); - /** \brief Parse for a specific given command line argument. Returns the value - * sent as an int. + /** \brief Parse for a specific given command line argument. * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] val the resultant value + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_argument (int argc, char** argv, const char* str, int &val); - /** \brief Parse for a specific given command line argument. Returns the value - * sent as an unsigned int. + /** \brief Parse for a specific given command line argument. * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] val the resultant value + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_argument (int argc, char** argv, const char* str, unsigned int &val); - /** \brief Parse for a specific given command line argument. Returns the value - * sent as an int. + /** \brief Parse for a specific given command line argument. * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] val the resultant value + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_argument (int argc, char** argv, const char* str, char &val); /** \brief Parse for specific given command line arguments (2x values comma - * separated). Returns the values sent as doubles. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] f the first output value * \param[out] s the second output value * \param[in] debug whether to print debug info or not + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_2x_arguments (int argc, char** argv, const char* str, float &f, float &s, bool debug = true); /** \brief Parse for specific given command line arguments (2x values comma - * separated). Returns the values sent as doubles. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] f the first output value * \param[out] s the second output value * \param[in] debug whether to print debug info or not + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_2x_arguments (int argc, char** argv, const char* str, double &f, double &s, bool debug = true); /** \brief Parse for specific given command line arguments (2x values comma - * separated). Returns the values sent as ints. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] f the first output value * \param[out] s the second output value * \param[in] debug whether to print debug info or not + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_2x_arguments (int argc, char** argv, const char* str, int &f, int &s, bool debug = true); /** \brief Parse for specific given command line arguments (3x values comma - * separated). Returns the values sent as doubles. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for @@ -205,12 +208,13 @@ namespace pcl * \param[out] s the second output value * \param[out] t the third output value * \param[in] debug whether to print debug info or not + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_3x_arguments (int argc, char** argv, const char* str, float &f, float &s, float &t, bool debug = true); /** \brief Parse for specific given command line arguments (3x values comma - * separated). Returns the values sent as doubles. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for @@ -218,12 +222,13 @@ namespace pcl * \param[out] s the second output value * \param[out] t the third output value * \param[in] debug whether to print debug info or not + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_3x_arguments (int argc, char** argv, const char* str, double &f, double &s, double &t, bool debug = true); /** \brief Parse for specific given command line arguments (3x values comma - * separated). Returns the values sent as ints. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for @@ -231,103 +236,111 @@ namespace pcl * \param[out] s the second output value * \param[out] t the third output value * \param[in] debug whether to print debug info or not + * return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_3x_arguments (int argc, char** argv, const char* str, int &f, int &s, int &t, bool debug = true); /** \brief Parse for specific given command line arguments (3x values comma - * separated). Returns the values sent as doubles. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] v the vector into which the parsed values will be copied + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_x_arguments (int argc, char** argv, const char* str, std::vector& v); /** \brief Parse for specific given command line arguments (N values comma - * separated). Returns the values sent as ints. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] v the vector into which the parsed values will be copied + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_x_arguments (int argc, char** argv, const char* str, std::vector& v); /** \brief Parse for specific given command line arguments (N values comma - * separated). Returns the values sent as ints. + * separated). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] v the vector into which the parsed values will be copied + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS int parse_x_arguments (int argc, char** argv, const char* str, std::vector& v); - /** \brief Parse for specific given command line arguments (multiple occurances - * of the same command line parameter). Returns the values sent as a vector. + /** \brief Parse for specific given command line arguments (multiple occurences + * of the same command line parameter). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] values the resultant output values + * \return index of found argument or -1 if arguments do not appear in list */ PCL_EXPORTS bool parse_multiple_arguments (int argc, char** argv, const char* str, std::vector &values); - /** \brief Parse for specific given command line arguments (multiple occurances - * of the same command line parameter). Returns the values sent as a vector. + /** \brief Parse for specific given command line arguments (multiple occurences + * of the same command line parameter). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] values the resultant output values + * \return true if found, false otherwise */ PCL_EXPORTS bool parse_multiple_arguments (int argc, char** argv, const char* str, std::vector &values); - /** \brief Parse for specific given command line arguments (multiple occurances - * of the same command line parameter). Returns the values sent as a vector. + /** \brief Parse for specific given command line arguments (multiple occurences + * of the same command line parameter). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] values the resultant output values + * \return true if found, false otherwise */ PCL_EXPORTS bool parse_multiple_arguments (int argc, char** argv, const char* str, std::vector &values); /** \brief Parse for a specific given command line argument (multiple occurences - * of the same command line parameter). Returns the value sent as a vector. + * of the same command line parameter). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the string value to search for * \param[out] values the resultant output values + * \return true if found, false otherwise */ PCL_EXPORTS bool parse_multiple_arguments (int argc, char** argv, const char* str, std::vector &values); - /** \brief Parse for specific given command line arguments (multiple occurances - * of 2x argument groups, separated by commas). Returns 2 vectors holding the - * given values. + /** \brief Parse command line arguments for file names with given extension (multiple occurences + * of 2x argument groups, separated by commas). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] values_f the first vector of output values * \param[out] values_s the second vector of output values + * \return true if found, false otherwise */ PCL_EXPORTS bool parse_multiple_2x_arguments (int argc, char** argv, const char* str, std::vector &values_f, std::vector &values_s); - /** \brief Parse for specific given command line arguments (multiple occurances - * of 3x argument groups, separated by commas). Returns 3 vectors holding the - * given values. + /** \brief Parse command line arguments for file names with given extension (multiple occurences + * of 3x argument groups, separated by commas). * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] str the command line argument to search for * \param[out] values_f the first vector of output values * \param[out] values_s the second vector of output values * \param[out] values_t the third vector of output values + * \return true if found, false otherwise */ PCL_EXPORTS bool parse_multiple_3x_arguments (int argc, char** argv, const char* str, @@ -335,11 +348,11 @@ namespace pcl std::vector &values_s, std::vector &values_t); - /** \brief Parse command line arguments for file names. Returns a vector with - * file names indices. + /** \brief Parse command line arguments for file names with given extension * \param[in] argc the number of command line arguments * \param[in] argv the command line arguments * \param[in] ext the extension to search for + * \return a vector with file names indices */ PCL_EXPORTS std::vector parse_file_extension_argument (int argc, char** argv, const std::string &ext); diff --git a/common/include/pcl/exceptions.h b/common/include/pcl/exceptions.h index 57c8ba65..b3462da9 100644 --- a/common/include/pcl/exceptions.h +++ b/common/include/pcl/exceptions.h @@ -251,6 +251,18 @@ namespace pcl : pcl::PCLException (error_description, file_name, function_name, line_number) { } }; + /** \class BadArgumentException + * \brief An exception that is thrown when the argments number or type is wrong/unhandled. + */ + class BadArgumentException : public PCLException + { + public: + BadArgumentException (const std::string& error_description, + const std::string& file_name = "", + const std::string& function_name = "" , + unsigned line_number = 0) throw () + : pcl::PCLException (error_description, file_name, function_name, line_number) { } + }; } diff --git a/common/include/pcl/impl/pcl_base.hpp b/common/include/pcl/impl/pcl_base.hpp index 67c2b6ea..7d4ae738 100644 --- a/common/include/pcl/impl/pcl_base.hpp +++ b/common/include/pcl/impl/pcl_base.hpp @@ -153,7 +153,7 @@ pcl::PCLBase::initCompute () } catch (std::bad_alloc) { - PCL_ERROR ("[initCompute] Failed to allocate %zu indices.\n", input_->points.size ()); + PCL_ERROR ("[initCompute] Failed to allocate %lu indices.\n", input_->points.size ()); } for (size_t i = 0; i < indices_->size (); ++i) { (*indices_)[i] = static_cast(i); } } diff --git a/common/include/pcl/impl/point_types.hpp b/common/include/pcl/impl/point_types.hpp index 748cd19d..c4a69ce4 100644 --- a/common/include/pcl/impl/point_types.hpp +++ b/common/include/pcl/impl/point_types.hpp @@ -72,6 +72,7 @@ (pcl::PFHSignature125) \ (pcl::PFHRGBSignature250) \ (pcl::PPFSignature) \ + (pcl::CPPFSignature) \ (pcl::PPFRGBSignature) \ (pcl::NormalBasedSignature12) \ (pcl::FPFHSignature33) \ @@ -131,6 +132,7 @@ (pcl::PFHSignature125) \ (pcl::PFHRGBSignature250) \ (pcl::PPFSignature) \ + (pcl::CPPFSignature) \ (pcl::PPFRGBSignature) \ (pcl::NormalBasedSignature12) \ (pcl::FPFHSignature33) \ @@ -141,7 +143,23 @@ namespace pcl { -#define PCL_ADD_POINT4D \ + typedef Eigen::Map Array3fMap; + typedef const Eigen::Map Array3fMapConst; + typedef Eigen::Map Array4fMap; + typedef const Eigen::Map Array4fMapConst; + typedef Eigen::Map Vector3fMap; + typedef const Eigen::Map Vector3fMapConst; + typedef Eigen::Map Vector4fMap; + typedef const Eigen::Map Vector4fMapConst; + + typedef Eigen::Matrix Vector3c; + typedef Eigen::Map Vector3cMap; + typedef const Eigen::Map Vector3cMapConst; + typedef Eigen::Matrix Vector4c; + typedef Eigen::Map Vector4cMap; + typedef const Eigen::Map Vector4cMapConst; + +#define PCL_ADD_UNION_POINT4D \ union EIGEN_ALIGN16 { \ float data[4]; \ struct { \ @@ -149,17 +167,23 @@ namespace pcl float y; \ float z; \ }; \ - }; \ - inline Eigen::Map getVector3fMap () { return (Eigen::Vector3f::Map (data)); } \ - inline const Eigen::Map getVector3fMap () const { return (Eigen::Vector3f::Map (data)); } \ - inline Eigen::Map getVector4fMap () { return (Eigen::Vector4f::MapAligned (data)); } \ - inline const Eigen::Map getVector4fMap () const { return (Eigen::Vector4f::MapAligned (data)); } \ - inline Eigen::Map getArray3fMap () { return (Eigen::Array3f::Map (data)); } \ - inline const Eigen::Map getArray3fMap () const { return (Eigen::Array3f::Map (data)); } \ - inline Eigen::Map getArray4fMap () { return (Eigen::Array4f::MapAligned (data)); } \ - inline const Eigen::Map getArray4fMap () const { return (Eigen::Array4f::MapAligned (data)); } + }; -#define PCL_ADD_NORMAL4D \ +#define PCL_ADD_EIGEN_MAPS_POINT4D \ + inline pcl::Vector3fMap getVector3fMap () { return (pcl::Vector3fMap (data)); } \ + inline pcl::Vector3fMapConst getVector3fMap () const { return (pcl::Vector3fMapConst (data)); } \ + inline pcl::Vector4fMap getVector4fMap () { return (pcl::Vector4fMap (data)); } \ + inline pcl::Vector4fMapConst getVector4fMap () const { return (pcl::Vector4fMapConst (data)); } \ + inline pcl::Array3fMap getArray3fMap () { return (pcl::Array3fMap (data)); } \ + inline pcl::Array3fMapConst getArray3fMap () const { return (pcl::Array3fMapConst (data)); } \ + inline pcl::Array4fMap getArray4fMap () { return (pcl::Array4fMap (data)); } \ + inline pcl::Array4fMapConst getArray4fMap () const { return (pcl::Array4fMapConst (data)); } + +#define PCL_ADD_POINT4D \ + PCL_ADD_UNION_POINT4D \ + PCL_ADD_EIGEN_MAPS_POINT4D + +#define PCL_ADD_UNION_NORMAL4D \ union EIGEN_ALIGN16 { \ float data_n[4]; \ float normal[3]; \ @@ -168,13 +192,19 @@ namespace pcl float normal_y; \ float normal_z; \ }; \ - }; \ - inline Eigen::Map getNormalVector3fMap () { return (Eigen::Vector3f::Map (data_n)); } \ - inline const Eigen::Map getNormalVector3fMap () const { return (Eigen::Vector3f::Map (data_n)); } \ - inline Eigen::Map getNormalVector4fMap () { return (Eigen::Vector4f::MapAligned (data_n)); } \ - inline const Eigen::Map getNormalVector4fMap () const { return (Eigen::Vector4f::MapAligned (data_n)); } + }; -#define PCL_ADD_RGB \ +#define PCL_ADD_EIGEN_MAPS_NORMAL4D \ + inline pcl::Vector3fMap getNormalVector3fMap () { return (pcl::Vector3fMap (data_n)); } \ + inline pcl::Vector3fMapConst getNormalVector3fMap () const { return (pcl::Vector3fMapConst (data_n)); } \ + inline pcl::Vector4fMap getNormalVector4fMap () { return (pcl::Vector4fMap (data_n)); } \ + inline pcl::Vector4fMapConst getNormalVector4fMap () const { return (pcl::Vector4fMapConst (data_n)); } + +#define PCL_ADD_NORMAL4D \ + PCL_ADD_UNION_NORMAL4D \ + PCL_ADD_EIGEN_MAPS_NORMAL4D + +#define PCL_ADD_UNION_RGB \ union \ { \ union \ @@ -191,6 +221,22 @@ namespace pcl uint32_t rgba; \ }; +#define PCL_ADD_EIGEN_MAPS_RGB \ + inline Eigen::Vector3i getRGBVector3i () { return (Eigen::Vector3i (r, g, b)); } \ + inline const Eigen::Vector3i getRGBVector3i () const { return (Eigen::Vector3i (r, g, b)); } \ + inline Eigen::Vector4i getRGBVector4i () { return (Eigen::Vector4i (r, g, b, a)); } \ + inline const Eigen::Vector4i getRGBVector4i () const { return (Eigen::Vector4i (r, g, b, a)); } \ + inline Eigen::Vector4i getRGBAVector4i () { return (Eigen::Vector4i (r, g, b, a)); } \ + inline const Eigen::Vector4i getRGBAVector4i () const { return (Eigen::Vector4i (r, g, b, a)); } \ + inline pcl::Vector3cMap getBGRVector3cMap () { return (pcl::Vector3cMap (reinterpret_cast (&rgba))); } \ + inline pcl::Vector3cMapConst getBGRVector3cMap () const { return (pcl::Vector3cMapConst (reinterpret_cast (&rgba))); } \ + inline pcl::Vector4cMap getBGRAVector4cMap () { return (pcl::Vector4cMap (reinterpret_cast (&rgba))); } \ + inline pcl::Vector4cMapConst getBGRAVector4cMap () const { return (pcl::Vector4cMapConst (reinterpret_cast (&rgba))); } + +#define PCL_ADD_RGB \ + PCL_ADD_UNION_RGB \ + PCL_ADD_EIGEN_MAPS_RGB + #define PCL_ADD_INTENSITY \ struct \ { \ @@ -209,15 +255,6 @@ namespace pcl uint32_t intensity; \ }; \ - typedef Eigen::Map Array3fMap; - typedef const Eigen::Map Array3fMapConst; - typedef Eigen::Map Array4fMap; - typedef const Eigen::Map Array4fMapConst; - typedef Eigen::Map Vector3fMap; - typedef const Eigen::Map Vector3fMapConst; - typedef Eigen::Map Vector4fMap; - typedef const Eigen::Map Vector4fMapConst; - struct _PointXYZ { @@ -346,6 +383,13 @@ namespace pcl intensity = 0; } +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 1101 + operator unsigned char() const + { + return intensity; + } +#endif + friend std::ostream& operator << (std::ostream& os, const Intensity8u& p); }; @@ -492,19 +536,10 @@ namespace pcl { x = y = z = 0.0f; data[3] = 1.0f; - r = g = b = a = 0; - } - inline Eigen::Vector3i getRGBVector3i () - { - return (Eigen::Vector3i (r, g, b)); - } - inline const Eigen::Vector3i getRGBVector3i () const { return (Eigen::Vector3i (r, g, b)); } - inline Eigen::Vector4i getRGBVector4i () - { - return (Eigen::Vector4i (r, g, b, a)); + r = g = b = 0; + a = 255; } - inline const Eigen::Vector4i getRGBVector4i () const { return (Eigen::Vector4i (r, g, b, a)); } - + friend std::ostream& operator << (std::ostream& os, const PointXYZRGBA& p); }; @@ -580,18 +615,6 @@ namespace pcl a = 0; } - inline Eigen::Vector3i getRGBVector3i () - { - return (Eigen::Vector3i (r, g, b)); - } - inline const Eigen::Vector3i getRGBVector3i () const { return (Eigen::Vector3i (r, g, b)); } - inline Eigen::Vector4i getRGBVector4i () - { - return (Eigen::Vector4i (r, g, b, a)); - } - inline const Eigen::Vector4i getRGBVector4i () const { return (Eigen::Vector4i (r, g, b, a)); } - - friend std::ostream& operator << (std::ostream& os, const PointXYZRGB& p); EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; @@ -847,23 +870,12 @@ namespace pcl { struct { - // RGB union - union - { - struct - { - uint8_t b; - uint8_t g; - uint8_t r; - uint8_t a; - }; - float rgb; - uint32_t rgba; - }; + PCL_ADD_UNION_RGB; float curvature; }; float data_c[4]; }; + PCL_ADD_EIGEN_MAPS_RGB; EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; @@ -916,17 +928,6 @@ namespace pcl curvature = 0; } - inline Eigen::Vector3i getRGBVector3i () - { - return (Eigen::Vector3i (r, g, b)); - } - inline const Eigen::Vector3i getRGBVector3i () const { return (Eigen::Vector3i (r, g, b)); } - inline Eigen::Vector4i getRGBVector4i () - { - return (Eigen::Vector4i (r, g, b, a)); - } - inline const Eigen::Vector4i getRGBVector4i () const { return (Eigen::Vector4i (r, g, b, a)); } - friend std::ostream& operator << (std::ostream& os, const PointXYZRGBNormal& p); }; @@ -1077,6 +1078,13 @@ namespace pcl struct Boundary { uint8_t boundary_point; + +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 1101 + operator unsigned char() const + { + return boundary_point; + } +#endif friend std::ostream& operator << (std::ostream& os, const Boundary& p); }; @@ -1110,6 +1118,7 @@ namespace pcl struct PFHSignature125 { float histogram[125]; + static int descriptorSize () { return 125; } friend std::ostream& operator << (std::ostream& os, const PFHSignature125& p); }; @@ -1121,7 +1130,8 @@ namespace pcl struct PFHRGBSignature250 { float histogram[250]; - + static int descriptorSize () { return 250; } + friend std::ostream& operator << (std::ostream& os, const PFHRGBSignature250& p); }; @@ -1137,6 +1147,18 @@ namespace pcl friend std::ostream& operator << (std::ostream& os, const PPFSignature& p); }; + PCL_EXPORTS std::ostream& operator << (std::ostream& os, const CPPFSignature& p); + /** \brief A point structure for storing the Point Pair Feature (CPPF) values + * \ingroup common + */ + struct CPPFSignature + { + float f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; + float alpha_m; + + friend std::ostream& operator << (std::ostream& os, const CPPFSignature& p); + }; + PCL_EXPORTS std::ostream& operator << (std::ostream& os, const PPFRGBSignature& p); /** \brief A point structure for storing the Point Pair Color Feature (PPFRGB) values * \ingroup common @@ -1170,7 +1192,8 @@ namespace pcl { float descriptor[1980]; float rf[9]; - + static int descriptorSize () { return 1980; } + friend std::ostream& operator << (std::ostream& os, const ShapeContext1980& p); }; @@ -1183,7 +1206,8 @@ namespace pcl { float descriptor[352]; float rf[9]; - + static int descriptorSize () { return 352; } + friend std::ostream& operator << (std::ostream& os, const SHOT352& p); }; @@ -1196,7 +1220,8 @@ namespace pcl { float descriptor[1344]; float rf[9]; - + static int descriptorSize () { return 1344; } + friend std::ostream& operator << (std::ostream& os, const SHOT1344& p); }; @@ -1256,7 +1281,8 @@ namespace pcl struct FPFHSignature33 { float histogram[33]; - + static int descriptorSize () { return 33; } + friend std::ostream& operator << (std::ostream& os, const FPFHSignature33& p); }; @@ -1267,7 +1293,8 @@ namespace pcl struct VFHSignature308 { float histogram[308]; - + static int descriptorSize () { return 308; } + friend std::ostream& operator << (std::ostream& os, const VFHSignature308& p); }; @@ -1278,7 +1305,8 @@ namespace pcl struct ESFSignature640 { float histogram[640]; - + static int descriptorSize () { return 640; } + friend std::ostream& operator << (std::ostream& os, const ESFSignature640& p); }; @@ -1289,7 +1317,7 @@ namespace pcl struct GFPFHSignature16 { float histogram[16]; - static int descriptorSize() { return 16; } + static int descriptorSize () { return 16; } friend std::ostream& operator << (std::ostream& os, const GFPFHSignature16& p); }; @@ -1302,7 +1330,8 @@ namespace pcl { float x, y, z, roll, pitch, yaw; float descriptor[36]; - + static int descriptorSize () { return 36; } + friend std::ostream& operator << (std::ostream& os, const Narf36& p); }; @@ -1347,6 +1376,7 @@ namespace pcl struct Histogram { float histogram[N]; + static int descriptorSize () { return N; } }; struct EIGEN_ALIGN16 _PointWithScale @@ -1431,25 +1461,14 @@ namespace pcl { struct { - // RGB union - union - { - struct - { - uint8_t b; - uint8_t g; - uint8_t r; - uint8_t a; - }; - float rgb; - uint32_t rgba; - }; + PCL_ADD_UNION_RGB; float radius; float confidence; float curvature; }; float data_c[4]; }; + PCL_ADD_EIGEN_MAPS_RGB; EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; diff --git a/common/include/pcl/pcl_base.h b/common/include/pcl/pcl_base.h index aabc529b..f678d99c 100644 --- a/common/include/pcl/pcl_base.h +++ b/common/include/pcl/pcl_base.h @@ -96,7 +96,7 @@ namespace pcl /** \brief Get a pointer to the input point cloud dataset. */ inline PointCloudConstPtr const - getInputCloud () { return (input_); } + getInputCloud () const { return (input_); } /** \brief Provide a pointer to the vector of indices that represents the input data. * \param[in] indices a pointer to the indices that represent the input data. @@ -131,12 +131,16 @@ namespace pcl inline IndicesPtr const getIndices () { return (indices_); } + /** \brief Get a pointer to the vector of indices used. */ + inline IndicesConstPtr const + getIndices () const { return (indices_); } + /** \brief Override PointCloud operator[] to shorten code * \note this method can be called instead of (*input_)[(*indices_)[pos]] * or input_->points[(*indices_)[pos]] * \param[in] pos position in indices_ vector */ - inline const PointT& operator[] (size_t pos) + inline const PointT& operator[] (size_t pos) const { return ((*input_)[(*indices_)[pos]]); } diff --git a/common/include/pcl/pcl_macros.h b/common/include/pcl/pcl_macros.h index 52594420..10969f9e 100644 --- a/common/include/pcl/pcl_macros.h +++ b/common/include/pcl/pcl_macros.h @@ -101,9 +101,9 @@ namespace pcl #elif ANDROID // Use the math.h macros # include -# define pcl_isnan(x) isnan(x) -# define pcl_isfinite(x) isfinite(x) -# define pcl_isinf(x) isinf(x) +# define pcl_isnan(x) std::isnan(x) +# define pcl_isfinite(x) std::isfinite(x) +# define pcl_isinf(x) std::isinf(x) #elif _GLIBCXX_USE_C99_MATH // Are the C++ cmath functions enabled? @@ -301,21 +301,21 @@ log2f (float x) #endif #if (defined(__GNUC__) && PCL_LINEAR_VERSION(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) < PCL_LINEAR_VERSION(4,5,0) && ! defined(__clang__)) || defined(__INTEL_COMPILER) -#define PCL_DEPRECATED(func, message) func __attribute__ ((deprecated)) +#define PCL_DEPRECATED(message) __attribute__ ((deprecated)) #endif // gcc supports this starting from 4.5 : http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43666 #if (defined(__GNUC__) && PCL_LINEAR_VERSION(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) >= PCL_LINEAR_VERSION(4,5,0)) || (defined(__clang__) && __has_extension(attribute_deprecated_with_message)) -#define PCL_DEPRECATED(func, message) func __attribute__ ((deprecated(message))) +#define PCL_DEPRECATED(message) __attribute__ ((deprecated(message))) #endif #ifdef _MSC_VER -#define PCL_DEPRECATED(func, message) __declspec(deprecated(message)) func +#define PCL_DEPRECATED(message) __declspec(deprecated(message)) #endif #ifndef PCL_DEPRECATED #pragma message("WARNING: You need to implement PCL_DEPRECATED for this compiler") -#define PCL_DEPRECATED(func) func +#define PCL_DEPRECATED(message) #endif diff --git a/common/include/pcl/pcl_tests.h b/common/include/pcl/pcl_tests.h index 10e7f99a..f9b8f136 100644 --- a/common/include/pcl/pcl_tests.h +++ b/common/include/pcl/pcl_tests.h @@ -40,16 +40,27 @@ #ifndef PCL_TEST_MACROS #define PCL_TEST_MACROS +#include + +/** \file pcl_tests.h + * Helper macros for testing equality of various data fields in PCL points */ + namespace pcl { + /** test_macros.h provide helper macros for testing vectors, matrices etc. * We took some liberty with upcasing names to make them look like googletest * macros names so that reader is not confused. * - * \author Nizar Sallem + * This file also provides a family of googletest-style macros for asserting + * equality or nearness of xyz, normal, and rgba fields. + * + * \author Nizar Sallem, Sergey Alexandrov */ + namespace test { + template void EXPECT_EQ_VECTORS (const V1& v1, const V2& v2) { @@ -69,7 +80,192 @@ namespace pcl for (size_t i = 0; i < length; ++i) EXPECT_NEAR (v1[i], v2[i], epsilon); } + + namespace internal + { + + template + ::testing::AssertionResult XYZEQ (const char* expr1, + const char* expr2, + const Point1T& p1, + const Point2T& p2) + { + if ((p1).getVector3fMap ().cwiseEqual ((p2).getVector3fMap ()).all ()) + return ::testing::AssertionSuccess (); + return ::testing::AssertionFailure () + << "Value of: " << expr2 << ".getVector3fMap ()" << std::endl + << " Actual: " << p2.getVector3fMap ().transpose () << std::endl + << "Expected: " << expr1 << ".getVector3fMap ()" << std::endl + << "Which is: " << p1.getVector3fMap ().transpose (); + } + + template + ::testing::AssertionResult XYZNear (const char* expr1, + const char* expr2, + const char* abs_error_expr, + const Point1T& p1, + const Point2T& p2, + double abs_error) + { + const Eigen::Vector3f diff = ((p1).getVector3fMap () - + (p2).getVector3fMap ()).cwiseAbs (); + if ((diff.array () < abs_error).all ()) + return ::testing::AssertionSuccess (); + return ::testing::AssertionFailure () + << "Some of the element-wise differences exceed " << abs_error_expr + << " (which evaluates to " << abs_error << ")" << std::endl + << "Difference: " << diff.transpose () << std::endl + << " Value of: " << expr2 << ".getVector3fMap ()" << std::endl + << " Actual: " << p2.getVector3fMap ().transpose () << std::endl + << " Expected: " << expr1 << ".getVector3fMap ()" << std::endl + << " Which is: " << p1.getVector3fMap ().transpose (); + } + + template + ::testing::AssertionResult NormalEQ (const char* expr1, + const char* expr2, + const Point1T& p1, + const Point2T& p2) + { + if ((p1).getNormalVector3fMap ().cwiseEqual ((p2).getNormalVector3fMap ()).all ()) + return ::testing::AssertionSuccess (); + return ::testing::AssertionFailure () + << "Value of: " << expr2 << ".getNormalVector3fMap ()" << std::endl + << " Actual: " << p2.getNormalVector3fMap ().transpose () << std::endl + << "Expected: " << expr1 << ".getNormalVector3fMap ()" << std::endl + << "Which is: " << p1.getNormalVector3fMap ().transpose (); + } + + template + ::testing::AssertionResult NormalNear (const char* expr1, + const char* expr2, + const char* abs_error_expr, + const Point1T& p1, + const Point2T& p2, + double abs_error) + { + const Eigen::Vector3f diff = ((p1).getNormalVector3fMap () - + (p2).getNormalVector3fMap ()).cwiseAbs (); + if ((diff.array () < abs_error).all ()) + return ::testing::AssertionSuccess (); + return ::testing::AssertionFailure () + << "Some of the element-wise differences exceed " << abs_error_expr + << " (which evaluates to " << abs_error << ")" << std::endl + << "Difference: " << diff.transpose () << std::endl + << " Value of: " << expr2 << ".getNormalVector3fMap ()" << std::endl + << " Actual: " << p2.getNormalVector3fMap ().transpose () << std::endl + << " Expected: " << expr1 << ".getNormalVector3fMap ()" << std::endl + << " Which is: " << p1.getNormalVector3fMap ().transpose (); + } + + template + ::testing::AssertionResult RGBEQ (const char* expr1, + const char* expr2, + const Point1T& p1, + const Point2T& p2) + { + if ((p1).getRGBVector3i ().cwiseEqual ((p2).getRGBVector3i ()).all ()) + return ::testing::AssertionSuccess (); + return ::testing::AssertionFailure () + << "Value of: " << expr2 << ".getRGBVector3i ()" << std::endl + << " Actual: " << p2.getRGBVector3i ().transpose () << std::endl + << "Expected: " << expr1 << ".getRGBVector3i ()" << std::endl + << "Which is: " << p1.getRGBVector3i ().transpose (); + } + + template + ::testing::AssertionResult RGBAEQ (const char* expr1, + const char* expr2, + const Point1T& p1, + const Point2T& p2) + { + if ((p1).getRGBAVector4i ().cwiseEqual ((p2).getRGBAVector4i ()).all ()) + return ::testing::AssertionSuccess (); + return ::testing::AssertionFailure () + << "Value of: " << expr2 << ".getRGBAVector4i ()" << std::endl + << " Actual: " << p2.getRGBAVector4i ().transpose () << std::endl + << "Expected: " << expr1 << ".getRGBAVector4i ()" << std::endl + << "Which is: " << p1.getRGBAVector4i ().transpose (); + } + + } + } + } +/// Expect that each of x, y, and z fields are equal in +/// two points. +#define EXPECT_XYZ_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::pcl::test::internal::XYZEQ, \ + (expected), (actual)) + +/// Assert that each of x, y, and z fields are equal in +/// two points. +#define ASSERT_XYZ_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::pcl::test::internal::XYZEQ, \ + (expected), (actual)) + +/// Expect that differences between x, y, and z fields in +/// two points are each within abs_error. +#define EXPECT_XYZ_NEAR(expected, actual, abs_error) \ + EXPECT_PRED_FORMAT3(::pcl::test::internal::XYZNear, \ + (expected), (actual), abs_error) + +/// Assert that differences between x, y, and z fields in +/// two points are each within abs_error. +#define ASSERT_XYZ_NEAR(expected, actual, abs_error) \ + EXPECT_PRED_FORMAT3(::pcl::test::internal::XYZNear, \ + (expected), (actual), abs_error) + +/// Expect that each of normal_x, normal_y, and normal_z +/// fields are equal in two points. +#define EXPECT_NORMAL_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::pcl::test::internal::NormalEQ, \ + (expected), (actual)) + +/// Assert that each of normal_x, normal_y, and normal_z +/// fields are equal in two points. +#define ASSERT_NORMAL_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::pcl::test::internal::NormalEQ, \ + (expected), (actual)) + +/// Expect that differences between normal_x, normal_y, +/// and normal_z fields in two points are each within +/// abs_error. +#define EXPECT_NORMAL_NEAR(expected, actual, abs_error) \ + EXPECT_PRED_FORMAT3(::pcl::test::internal::NormalNear, \ + (expected), (actual), abs_error) + +/// Assert that differences between normal_x, normal_y, +/// and normal_z fields in two points are each within +/// abs_error. +#define ASSERT_NORMAL_NEAR(expected, actual, abs_error) \ + EXPECT_PRED_FORMAT3(::pcl::test::internal::NormalNear, \ + (expected), (actual), abs_error) + +/// Expect that each of r, g, and b fields are equal in +/// two points. +#define EXPECT_RGB_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::pcl::test::internal::RGBEQ, \ + (expected), (actual)) + +/// Assert that each of r, g, and b fields are equal in +/// two points. +#define ASSERT_RGB_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::pcl::test::internal::RGBEQ, \ + (expected), (actual)) + +/// Expect that each of r, g, b, and a fields are equal +/// in two points. +#define EXPECT_RGBA_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::pcl::test::internal::RGBAEQ, \ + (expected), (actual)) + +/// Assert that each of r, g, b, and a fields are equal +/// in two points. +#define ASSERT_RGBA_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::pcl::test::internal::RGBAEQ, \ + (expected), (actual)) + #endif diff --git a/common/include/pcl/point_traits.h b/common/include/pcl/point_traits.h index f10d9374..7d3d97a1 100644 --- a/common/include/pcl/point_traits.h +++ b/common/include/pcl/point_traits.h @@ -53,6 +53,12 @@ #include #endif +// This is required for the workaround at line 109 +#ifdef _MSC_VER +#include +#include +#endif + namespace pcl { @@ -100,6 +106,24 @@ namespace pcl typedef PointT type; }; +#ifdef _MSC_VER + + /* Sometimes when calling functions like `copyPoint()` or `copyPointCloud` + * without explicitly specifying point types, MSVC deduces them to be e.g. + * `Eigen::internal::workaround_msvc_stl_support` instead of + * plain `pcl::PointXYZ`. Subsequently these types are passed to meta- + * functions like `has_field` or `fieldList` and make them choke. This hack + * makes use of the fact that internally `fieldList` always applies `POD` to + * its argument type. This specialization therefore allows to unwrap the + * contained point type. */ + template + struct POD > + { + typedef PointT type; + }; + +#endif + // name /* This really only depends on Tag, but we go through some gymnastics to avoid ODR violations. We template it on the point type PointT to avoid ODR violations when registering multiple @@ -185,7 +209,19 @@ namespace pcl } }; - /** \brief A helper functor that can copy a specific value if the given field exists. */ + /** \brief A helper functor that can copy a specific value if the given field exists. + * + * \note In order to actually copy the value an instance of this functor should be passed + * to a pcl::for_each_type loop. See the example below. + * + * \code + * PointInT p; + * bool exists; + * float value; + * typedef typename pcl::traits::fieldList::type FieldList; + * pcl::for_each_type (pcl::CopyIfFieldExists (p, "intensity", exists, value)); + * \endcode + */ template struct CopyIfFieldExists { @@ -240,7 +276,17 @@ namespace pcl OutT &value_; }; - /** \brief A helper functor that can set a specific value in a field if the field exists. */ + /** \brief A helper functor that can set a specific value in a field if the field exists. + * + * \note In order to actually set the value an instance of this functor should be passed + * to a pcl::for_each_type loop. See the example below. + * + * \code + * PointT p; + * typedef typename pcl::traits::fieldList::type FieldList; + * pcl::for_each_type (pcl::SetIfFieldExists (p, "intensity", 42.0f)); + * \endcode + */ template struct SetIfFieldExists { diff --git a/common/include/pcl/point_types.h b/common/include/pcl/point_types.h index 6635426b..0bce7712 100644 --- a/common/include/pcl/point_types.h +++ b/common/include/pcl/point_types.h @@ -42,6 +42,9 @@ #include #include #include +#include +#include +#include /** * \file pcl/point_types.h @@ -227,6 +230,11 @@ namespace pcl */ struct PPFSignature; + /** \brief Members: float f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, alpha_m + * \ingroup common + */ + struct CPPFSignature; + /** \brief Members: float f1, f2, f3, f4, r_ratio, g_ratio, b_ratio, alpha_m * \ingroup common */ @@ -513,6 +521,20 @@ POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::PPFSignature, (float, alpha_m, alpha_m) ) +POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::CPPFSignature, + (float, f1, f1) + (float, f2, f2) + (float, f3, f3) + (float, f4, f4) + (float, f5, f5) + (float, f6, f6) + (float, f7, f7) + (float, f8, f8) + (float, f9, f9) + (float, f10, f10) + (float, alpha_m, alpha_m) +) + POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::PPFRGBSignature, (float, f1, f1) (float, f2, f2) @@ -636,6 +658,84 @@ namespace pcl } } }; + + namespace traits + { + + /** \brief Metafunction to check if a given point type has a given field. + * + * Example usage at run-time: + * + * \code + * bool curvature_available = pcl::traits::has_field::value; + * \endcode + * + * Example usage at compile-time: + * + * \code + * BOOST_MPL_ASSERT_MSG ((pcl::traits::has_field::value), + * POINT_TYPE_SHOULD_HAVE_LABEL_FIELD, + * (PointT)); + * \endcode + */ + template + struct has_field : boost::mpl::contains::type, Field>::type + { }; + + /** Metafunction to check if a given point type has all given fields. */ + template + struct has_all_fields : boost::mpl::fold, + boost::mpl::and_ > >::type + { }; + + /** Metafunction to check if a given point type has any of the given fields. */ + template + struct has_any_field : boost::mpl::fold, + boost::mpl::or_ > >::type + { }; + + /** Metafunction to check if a given point type has x, y, and z fields. */ + template + struct has_xyz : has_all_fields > + { }; + + /** Metafunction to check if a given point type has normal_x, normal_y, and + * normal_z fields. */ + template + struct has_normal : has_all_fields > + { }; + + /** Metafunction to check if a given point type has curvature field. */ + template + struct has_curvature : has_field + { }; + + /** Metafunction to check if a given point type has intensity field. */ + template + struct has_intensity : has_field + { }; + + /** Metafunction to check if a given point type has either rgb or rgba field. */ + template + struct has_color : has_any_field > + { }; + + /** Metafunction to check if a given point type has label field. */ + template + struct has_label : has_field + { }; + + } + } // namespace pcl #if defined _MSC_VER diff --git a/common/include/pcl/point_types_conversion.h b/common/include/pcl/point_types_conversion.h index fe867f53..1f445ca8 100644 --- a/common/include/pcl/point_types_conversion.h +++ b/common/include/pcl/point_types_conversion.h @@ -179,7 +179,7 @@ namespace pcl out.x = in.x; out.y = in.y; out.z = in.z; if (in.s == 0) { - out.r = out.g = out.b = static_cast (in.v); + out.r = out.g = out.b = static_cast (255 * in.v); return; } float a = in.h / 60; @@ -350,24 +350,24 @@ namespace pcl * \param[in] focal the focal length * \param[out] out the output pointcloud * **/ - void + inline void PointCloudDepthAndRGBtoXYZRGBA (PointCloud& depth, PointCloud& image, float& focal, PointCloud& out) { float bad_point = std::numeric_limits::quiet_NaN(); - int width_ = depth.width; - int height_ = depth.height; + size_t width_ = depth.width; + size_t height_ = depth.height; float constant_ = 1.0f / focal; - for(unsigned int v = 0; v < height_; v++) + for (size_t v = 0; v < height_; v++) { - for(unsigned int u = 0; u < width_; u++) + for (size_t u = 0; u < width_; u++) { PointXYZRGBA pt; pt.a = 0; - float depth_ = depth.at(u,v).intensity; + float depth_ = depth.at (u, v).intensity; if (depth_ == 0) { @@ -379,11 +379,11 @@ namespace pcl pt.x = static_cast (u) * pt.z * constant_; pt.y = static_cast (v) * pt.z * constant_; } - pt.r = image.at(u,v).r; - pt.g = image.at(u,v).g; - pt.b = image.at(u,v).b; + pt.r = image.at (u, v).r; + pt.g = image.at (u, v).g; + pt.b = image.at (u, v).b; - out.points.push_back(pt); + out.points.push_back (pt); } } out.width = width_; diff --git a/common/include/pcl/range_image/bearing_angle_image.h b/common/include/pcl/range_image/bearing_angle_image.h new file mode 100644 index 00000000..2245ea52 --- /dev/null +++ b/common/include/pcl/range_image/bearing_angle_image.h @@ -0,0 +1,89 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2013, Intelligent Robotics Lab, DLUT. + * Author: Qinghua Li, Yan Zhuang, Fei Yan + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intelligent Robotics Lab, DLUT. nor the names + * of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file bearing_angle_image.h + * \Created on: July 07, 2012 + */ + +#ifndef PCL_BEARING_ANGLE_IMAGE_H_ +#define PCL_BEARING_ANGLE_IMAGE_H_ + +#include +#include +#include + +namespace pcl +{ + /** \brief class BearingAngleImage is used as an interface to generate Bearing Angle(BA) image. + * \author: Qinghua Li (qinghua__li@163.com) + */ + class BearingAngleImage : public pcl::PointCloud + { + public: + // ===== TYPEDEFS ===== + typedef pcl::PointCloud BaseClass; + + // =====CONSTRUCTOR & DESTRUCTOR===== + /** Constructor */ + BearingAngleImage (); + /** Destructor */ + virtual ~BearingAngleImage (); + + public: + /** \brief Reset all values to an empty Bearing Angle image */ + void + reset (); + + /** \brief Calculate the angle between the laser beam and the segment joining two consecutive + * measurement points. + * \param point1 + * \param point2 + */ + double + getAngle (const PointXYZ &point1, const PointXYZ &point2); + + /** \brief Transform 3D point cloud into a 2D Bearing Angle(BA) image */ + void + generateBAImage (PointCloud& point_cloud); + + protected: + /**< This point is used to be able to return a reference to a unknown gray point */ + PointXYZRGBA unobserved_point_; + }; +} + +#endif // PCL_BEARING_ANGLE_IMAGE_H_ diff --git a/common/include/pcl/range_image/range_image.h b/common/include/pcl/range_image/range_image.h index 765921b4..79b1d65f 100644 --- a/common/include/pcl/range_image/range_image.h +++ b/common/include/pcl/range_image/range_image.h @@ -203,7 +203,6 @@ namespace pcl * individual pixels in the image in the x-direction * \param angular_resolution_y the angular difference (in radians) between the * individual pixels in the image in the y-direction - * \param angular_resolution the angle (in radians) between each sample in the depth image * \param point_cloud_center the center of bounding sphere * \param point_cloud_radius the radius of the bounding sphere * \param sensor_pose an affine matrix defining the pose of the sensor (defaults to diff --git a/common/include/pcl/ros/conversions.h b/common/include/pcl/ros/conversions.h index b1544434..41d47f93 100644 --- a/common/include/pcl/ros/conversions.h +++ b/common/include/pcl/ros/conversions.h @@ -62,12 +62,9 @@ namespace pcl * createMapping (msg.fields, field_map); * \endcode */ - PCL_DEPRECATED (template void fromROSMsg ( - const pcl::PCLPointCloud2& msg, pcl::PointCloud& cloud, - const MsgFieldMap& field_map), - "pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead."); - - template void + template + PCL_DEPRECATED ("pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead.") + void fromROSMsg (const pcl::PCLPointCloud2& msg, pcl::PointCloud& cloud, const MsgFieldMap& field_map) { @@ -78,10 +75,9 @@ namespace pcl * \param[in] msg the PCLPointCloud2 binary blob * \param[out] cloud the resultant pcl::PointCloud */ - PCL_DEPRECATED (template void fromROSMsg ( - const pcl::PCLPointCloud2& msg, pcl::PointCloud& cloud), - "pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead."); - template void + template + PCL_DEPRECATED ("pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead.") + void fromROSMsg (const pcl::PCLPointCloud2& msg, pcl::PointCloud& cloud) { fromPCLPointCloud2 (msg, cloud); @@ -91,10 +87,9 @@ namespace pcl * \param[in] cloud the input pcl::PointCloud * \param[out] msg the resultant PCLPointCloud2 binary blob */ - PCL_DEPRECATED (template void toROSMsg ( - const pcl::PointCloud& cloud, pcl::PCLPointCloud2& msg), - "pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead."); - template void + template + PCL_DEPRECATED ("pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead.") + void toROSMsg (const pcl::PointCloud& cloud, pcl::PCLPointCloud2& msg) { toPCLPointCloud2 (cloud, msg); @@ -106,10 +101,9 @@ namespace pcl * CloudT cloud type, CloudT should be akin to pcl::PointCloud * \note will throw std::runtime_error if there is a problem */ - PCL_DEPRECATED (template void toROSMsg ( - const CloudT& cloud, pcl::PCLImage& msg), - "pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead."); - template void + template + PCL_DEPRECATED ("pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead.") + void toROSMsg (const CloudT& cloud, pcl::PCLImage& msg) { toPCLPointCloud2 (cloud, msg); @@ -120,10 +114,8 @@ namespace pcl * \param msg the resultant pcl::PCLImage * will throw std::runtime_error if there is a problem */ - PCL_DEPRECATED (inline void toROSMsg ( - const pcl::PCLPointCloud2& cloud, pcl::PCLImage& msg), - "pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead."); inline void + PCL_DEPRECATED ("pcl::fromROSMsg is deprecated, please use fromPCLPointCloud2 instead.") toROSMsg (const pcl::PCLPointCloud2& cloud, pcl::PCLImage& msg) { toPCLPointCloud2 (cloud, msg); diff --git a/common/src/bearing_angle_image.cpp b/common/src/bearing_angle_image.cpp new file mode 100644 index 00000000..bdb72b57 --- /dev/null +++ b/common/src/bearing_angle_image.cpp @@ -0,0 +1,130 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2013, Intelligent Robotics Lab, DLUT. + * Author: Qinghua Li, Yan Zhuang, Fei Yan + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intelligent Robotics Lab, DLUT. nor the names + * of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file bearing_angle_image.cpp + * \created on: July 07, 2012 + * \author: Qinghua Li (qinghua__li@163.com) + */ + +#include +#include + +namespace pcl +{ +///////////////////////////////////////////////////////// +BearingAngleImage::BearingAngleImage () : + BearingAngleImage::BaseClass (), + unobserved_point_ () +{ + reset (); + unobserved_point_.x = unobserved_point_.y = unobserved_point_.z = 0.0; + unobserved_point_.rgba = 255; +} + +///////////////////////////////////////////////////////// +BearingAngleImage::~BearingAngleImage () +{ +} + +///////////////////////////////////////////////////////// +void +BearingAngleImage::reset () +{ + width = height = 0; + points.clear (); +} + +///////////////////////////////////////////////////////// +double +BearingAngleImage::getAngle (const PointXYZ &point1, const PointXYZ &point2) +{ + double a, b, c; + double theta; + const Eigen::Vector3f& p1 = point1.getVector3fMap (); + const Eigen::Vector3f& p2 = point2.getVector3fMap (); + a = p1.squaredNorm (); + b = (p1 - p2).squaredNorm (); + c = p2.squaredNorm (); + + if (a != 0 && b != 0) + { + theta = acos ((a + b - c) / (2 * sqrt (a) * sqrt (b))) * 180 / M_PI; + } + else + { + theta = 0.0; + } + + return theta; +} + +///////////////////////////////////////////////////////// +void +BearingAngleImage::generateBAImage (PointCloud& point_cloud) +{ + width = point_cloud.width; + height = point_cloud.height; + unsigned int size = width * height; + points.clear (); + points.resize (size, unobserved_point_); + + double theta; + uint8_t r, g, b, gray; + + // primary transformation process + for (int i = 0; i < static_cast (height) - 1; ++i) + { + for (int j = 0; j < static_cast (width) - 1; ++j) + { + theta = getAngle (point_cloud.at (j, i + 1), point_cloud.at (j + 1, i)); + + // based on the theta, calculate the gray value of every pixel point + gray = theta * 255 / 180; + r = gray; + g = gray; + b = gray; + + points[(i + 1) * width + j].x = point_cloud.at (j, i + 1).x; + points[(i + 1) * width + j].y = point_cloud.at (j, i + 1).y; + points[(i + 1) * width + j].z = point_cloud.at (j, i + 1).z; + // set the gray value for every pixel point + points[(i + 1) * width + j].rgba = ((int)r) << 24 | ((int)g) << 16 | ((int)b) << 8 | 0xff; + } + } +} + +} // namespace end diff --git a/common/src/intersections.cpp b/common/src/intersections.cpp deleted file mode 100644 index 6176ba08..00000000 --- a/common/src/intersections.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Software License Agreement (BSD License) - * - * Copyright (c) 2010, Willow Garage, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of the copyright holder(s) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $Id$ - * - */ - -#include -#include - -bool -pcl::lineWithLineIntersection (const Eigen::VectorXf &line_a, - const Eigen::VectorXf &line_b, - Eigen::Vector4f &point, double sqr_eps) -{ - Eigen::Vector4f p1, p2; - lineToLineSegment (line_a, line_b, p1, p2); - - // If the segment size is smaller than a pre-given epsilon... - double sqr_dist = (p1 - p2).squaredNorm (); - if (sqr_dist < sqr_eps) - { - point = p1; - return (true); - } - point.setZero (); - return (false); -} - -bool -pcl::lineWithLineIntersection (const pcl::ModelCoefficients &line_a, - const pcl::ModelCoefficients &line_b, - Eigen::Vector4f &point, double sqr_eps) -{ - Eigen::VectorXf coeff1 = Eigen::VectorXf::Map (&line_a.values[0], line_a.values.size ()); - Eigen::VectorXf coeff2 = Eigen::VectorXf::Map (&line_b.values[0], line_b.values.size ()); - return (lineWithLineIntersection (coeff1, coeff2, point, sqr_eps)); -} - -bool -pcl::planeWithPlaneIntersection (const Eigen::Vector4f &plane_a, - const Eigen::Vector4f &plane_b, - Eigen::VectorXf &line, - double angular_tolerance) -{ - //planes shouldn't be parallel - double test_cosine = plane_a.head<3>().dot(plane_b.head<3>()); - double upper_limit = 1 + angular_tolerance; - double lower_limit = 1 - angular_tolerance; - - if ((test_cosine < upper_limit) && (test_cosine > lower_limit)) - { - PCL_ERROR ("Plane A and Plane B are Parallel"); - return (false); - } - - if ((test_cosine > -upper_limit) && (test_cosine < -lower_limit)) - { - PCL_ERROR ("Plane A and Plane B are Parallel"); - return (false); - } - - Eigen::Vector4f line_direction = plane_a.cross3(plane_b); - line_direction.normalized(); - - //construct system of equations using lagrange multipliers with one objective function and two constraints - Eigen::MatrixXf langegrange_coefs(5,5); - langegrange_coefs << 2,0,0,plane_a[0],plane_b[0], 0,2,0,plane_a[1],plane_b[1], 0,0,2, plane_a[2], plane_b[2], plane_a[0], plane_a[1] , plane_a[2], 0,0, plane_b[0], plane_b[1], plane_b[2], 0,0; - - Eigen::VectorXf b; - b.resize(5); - b << 0, 0, 0, -plane_a[3], -plane_b[3]; - - //solve for the lagrange Multipliers - Eigen::VectorXf x; - x.resize(5); - x = langegrange_coefs.colPivHouseholderQr().solve(b); - - line.resize(6); - line.head<3>() = x.head<3>(); // the x[3] and x[4] are the values of the lagrange multipliers and are neglected - line[3] = line_direction[0]; - line[4] = line_direction[1]; - line[5] = line_direction[2]; - return true; -} diff --git a/common/src/io.cpp b/common/src/io.cpp index 561d0b13..cd260873 100644 --- a/common/src/io.cpp +++ b/common/src/io.cpp @@ -474,3 +474,44 @@ pcl::copyPointCloud (const pcl::PCLPointCloud2 &cloud_in, cloud_out.data = cloud_in.data; } +//////////////////////////////////////////////////////////////////////////////// +int +pcl::interpolatePointIndex (int p, int len, InterpolationType type) +{ + if (static_cast (p) >= static_cast (len)) + { + if (type == BORDER_REPLICATE) + p = p < 0 ? 0 : len - 1; + else if (type == BORDER_REFLECT || type == BORDER_REFLECT_101) + { + int delta = type == BORDER_REFLECT_101; + if (len == 1) + return 0; + do + { + if (p < 0) + p = -p - 1 + delta; + else + p = len - 1 - (p - len) - delta; + } + while (static_cast (p) >= static_cast (len)); + } + else if (type == BORDER_WRAP) + { + if (p < 0) + p -= ((p-len+1)/len)*len; + if (p >= len) + p %= len; + } + else if (type == BORDER_CONSTANT) + p = -1; + else + { + PCL_THROW_EXCEPTION (BadArgumentException, + "[pcl::interpolate_point_index] error: Unhandled interpolation type " + << type << " !"); + } + } + + return (p); +} diff --git a/common/src/parse.cpp b/common/src/parse.cpp index 8cf87d1a..308243ae 100644 --- a/common/src/parse.cpp +++ b/common/src/parse.cpp @@ -191,7 +191,7 @@ pcl::console::parse_2x_arguments (int argc, char** argv, const char* str, float boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 2 && debug) { - print_error ("[parse_2x_arguments] Number of values for %s (%zu) different than 2!\n", str, values.size ()); + print_error ("[parse_2x_arguments] Number of values for %s (%lu) different than 2!\n", str, values.size ()); return (-2); } f = static_cast (atof (values.at (0).c_str ())); @@ -216,7 +216,7 @@ pcl::console::parse_2x_arguments (int argc, char** argv, const char* str, double boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 2 && debug) { - print_error ("[parse_2x_arguments] Number of values for %s (%zu) different than 2!\n", str, values.size ()); + print_error ("[parse_2x_arguments] Number of values for %s (%lu) different than 2!\n", str, values.size ()); return (-2); } f = atof (values.at (0).c_str ()); @@ -241,7 +241,7 @@ pcl::console::parse_2x_arguments (int argc, char** argv, const char* str, int &f boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 2 && debug) { - print_error ("[parse_2x_arguments] Number of values for %s (%zu) different than 2!\n", str, values.size ()); + print_error ("[parse_2x_arguments] Number of values for %s (%lu) different than 2!\n", str, values.size ()); return (-2); } f = atoi (values.at (0).c_str ()); @@ -266,7 +266,7 @@ pcl::console::parse_3x_arguments (int argc, char** argv, const char* str, float boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 3 && debug) { - print_error ("[parse_3x_arguments] Number of values for %s (%zu) different than 3!\n", str, values.size ()); + print_error ("[parse_3x_arguments] Number of values for %s (%lu) different than 3!\n", str, values.size ()); return (-2); } f = static_cast (atof (values.at (0).c_str ())); @@ -292,7 +292,7 @@ pcl::console::parse_3x_arguments (int argc, char** argv, const char* str, double boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 3 && debug) { - print_error ("[parse_3x_arguments] Number of values for %s (%zu) different than 3!\n", str, values.size ()); + print_error ("[parse_3x_arguments] Number of values for %s (%lu) different than 3!\n", str, values.size ()); return (-2); } f = atof (values.at (0).c_str ()); @@ -318,7 +318,7 @@ pcl::console::parse_3x_arguments (int argc, char** argv, const char* str, int &f boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 3 && debug) { - print_error ("[parse_3x_arguments] Number of values for %s (%zu) different than 3!\n", str, values.size ()); + print_error ("[parse_3x_arguments] Number of values for %s (%lu) different than 3!\n", str, values.size ()); return (-2); } f = atoi (values.at (0).c_str ()); @@ -489,7 +489,7 @@ pcl::console::parse_multiple_2x_arguments (int argc, char** argv, const char* st boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 2) { - print_error ("[parse_multiple_2x_arguments] Number of values for %s (%zu) different than 2!\n", str, values.size ()); + print_error ("[parse_multiple_2x_arguments] Number of values for %s (%lu) different than 2!\n", str, values.size ()); return (false); } f = atof (values.at (0).c_str ()); @@ -522,7 +522,7 @@ pcl::console::parse_multiple_3x_arguments (int argc, char** argv, const char* st boost::split (values, argv[i], boost::is_any_of (","), boost::token_compress_on); if (values.size () != 3) { - print_error ("[parse_multiple_3x_arguments] Number of values for %s (%zu) different than 3!\n", str, values.size ()); + print_error ("[parse_multiple_3x_arguments] Number of values for %s (%lu) different than 3!\n", str, values.size ()); return (false); } f = atof (values.at (0).c_str ()); diff --git a/common/src/pcl_base.cpp b/common/src/pcl_base.cpp index 963faa03..215c7243 100644 --- a/common/src/pcl_base.cpp +++ b/common/src/pcl_base.cpp @@ -142,7 +142,7 @@ pcl::PCLBase::initCompute () } catch (std::bad_alloc) { - PCL_ERROR ("[initCompute] Failed to allocate %zu indices.\n", (input_->width * input_->height)); + PCL_ERROR ("[initCompute] Failed to allocate %lu indices.\n", (input_->width * input_->height)); } for (size_t i = 0; i < indices_->size (); ++i) { (*indices_)[i] = static_cast(i); } } diff --git a/common/src/point_types.cpp b/common/src/point_types.cpp index 4c78ce04..cdecebd1 100644 --- a/common/src/point_types.cpp +++ b/common/src/point_types.cpp @@ -254,6 +254,13 @@ namespace pcl return (os); } + std::ostream& + operator << (std::ostream& os, const CPPFSignature& p) + { + os << "(" << p.f1 << ", " << p.f2 << ", " << p.f3 << ", " << p.f4 << ", " << p.f5 << ", " << p.f6 << ", " << p.f7 << ", " << p.f8 << ", " << p.f9 << ", " << p.f10 << ", " << p.alpha_m << ")"; + return (os); + } + std::ostream& operator << (std::ostream& os, const PPFRGBSignature& p) { diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index c6300b8c..c43826f2 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,2 +1,14 @@ +include(CMakeDependentOption) + +cmake_dependent_option(WITH_TUTORIALS "Build tutorials (requires Sphinx)" FALSE "WITH_DOCS" FALSE) +if(WITH_TUTORIALS) + find_package(Sphinx) + if(SPHINX_FOUND) + set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees") + set(SPHINX_HTML_FILE_SUFFIX "html" CACHE STRING "Suffix (extension) of the HTML files generated by Sphinx") + endif(SPHINX_FOUND) +endif(WITH_TUTORIALS) + add_subdirectory(doxygen) +add_subdirectory(advanced) add_subdirectory(tutorials) diff --git a/doc/advanced/CMakeLists.txt b/doc/advanced/CMakeLists.txt new file mode 100644 index 00000000..d066c438 --- /dev/null +++ b/doc/advanced/CMakeLists.txt @@ -0,0 +1,14 @@ +if(SPHINX_FOUND) + add_custom_target(advanced ALL + COMMAND "${SPHINX_EXECUTABLE}" -b html -a -d "${SPHINX_CACHE_DIR}" -D html_file_suffix=".${SPHINX_HTML_FILE_SUFFIX}" "${CMAKE_CURRENT_SOURCE_DIR}/content" html) + add_dependencies(advanced doc) + if(USE_PROJECT_FOLDERS) + set_target_properties(advanced PROPERTIES FOLDER "Documentation (Advanced)") + endif(USE_PROJECT_FOLDERS) + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" + DESTINATION "${DOC_INSTALL_DIR}/advanced" + COMPONENT doc) + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/content/files" + DESTINATION "${DOC_INSTALL_DIR}/advanced" + COMPONENT doc) +endif(SPHINX_FOUND) diff --git a/doc/advanced/Makefile b/doc/advanced/Makefile deleted file mode 100644 index 46fe7754..00000000 --- a/doc/advanced/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -.PHONY: html - -html: - -rm -rf html /tmp/doctrees - sphinx-build -b html -a -d /tmp/doctrees content html - diff --git a/doc/advanced/content/_static/basic.css b/doc/advanced/content/_static/basic.css new file mode 100644 index 00000000..efe60182 --- /dev/null +++ b/doc/advanced/content/_static/basic.css @@ -0,0 +1,538 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +img { + border: 0; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { +font-family: "Droid Serif", "DejaVu Serif", "Garamond", serif; +font-size: 1.3em; +color: #64794c; +margin-bottom: 0; + margin-top: 0 !important; +} + +.first img { +max-width: none !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + clear: both; + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.refcount { + color: #060; +} + +.optional { + font-size: 1.3em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +white-space : pre-wrap; /*for Mozilla*/ +word-wrap: break-word; /*for IE*/ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +tt.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +tt.descclassname { + background-color: transparent; +} + +tt.xref, a tt { + background-color: transparent; + font-weight: bold; +} + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} diff --git a/doc/advanced/content/_static/sphinxdoc.css b/doc/advanced/content/_static/sphinxdoc.css new file mode 100644 index 00000000..62ff7fd6 --- /dev/null +++ b/doc/advanced/content/_static/sphinxdoc.css @@ -0,0 +1,315 @@ +/* + * sphinxdoc.css_t + * ~~~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- sphinxdoc theme. Originally created by + * Armin Ronacher for Werkzeug. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + color: black; + padding: 0; + margin: 0px 80px 0px 80px; + min-width: 740px; +} + +div.document { + + text-align: left; + + +} + +div.bodywrapper { + margin: 0 240px 0 0; + border-right: 1px solid #ccc; +} + +div.body { + margin: 0; + padding: 0.5em 20px 20px 20px; +} + +div.related { + font-size: 1em; +} + +div.related ul { + background-image: url(navigation.png); + height: 2em; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} + +div.related ul li { + margin: 0; + padding: 0; + height: 2em; + float: left; +} + +div.related ul li.right { + float: right; + margin-right: 5px; +} + +div.related ul li a { + margin: 0; + padding: 0 5px 0 5px; + line-height: 1.75em; + color: #EE9816; +} + +div.related ul li a:hover { + color: #3CA8E7; +} + +div.sphinxsidebarwrapper { + padding: 0; +} + +div.sphinxsidebar { + margin: 0; + padding: 0.5em 15px 15px 0; + width: 210px; + float: right; + font-size: 1em; + text-align: left; +} + +div.sphinxsidebar h3, div.sphinxsidebar h4 { + margin: 1em 0 0.5em 0; + font-size: 1em; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border: 1px solid #86989B; + background-color: #AFC1C4; +} + +div.sphinxsidebar h3 a { + color: white; +} + +div.sphinxsidebar ul { + padding-left: 1.5em; + margin-top: 7px; + padding: 0; + line-height: 130%; +} + +div.sphinxsidebar ul ul { + margin-left: 20px; +} + +div.footer { + background-color: #E3EFF1; + color: #86989B; + padding: 3px 8px 3px 0; + clear: both; + font-size: 0.8em; + text-align: right; +} + +div.footer a { + color: #86989B; + text-decoration: underline; +} + +/* -- body styles ----------------------------------------------------------- */ + +p { + margin: 0.8em 0 0.5em 0; +} + +div.body a { + text-decoration: underline; +} + +h2 { +/* color: #11557C;*/ + margin: 1.3em 0 0.2em 0; + font-size: 1.35em; + padding: 0; +} + +h3 { + margin: 1em 0 -0.3em 0; + font-size: 1.2em; +} + +div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a { + color: black!important; +} + +h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { + display: none; + margin: 0 0 0 0.3em; + padding: 0 0.2em 0 0.2em; + color: #aaa!important; +} + +h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, +h5:hover a.anchor, h6:hover a.anchor { + display: inline; +} + +h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, +h5 a.anchor:hover, h6 a.anchor:hover { + color: #777; + background-color: #eee; +} + +a.headerlink { + color: #c60f0f!important; + font-size: 1em; + margin-left: 6px; + padding: 0 4px 0 4px; + text-decoration: none!important; +} + +a.headerlink:hover { + background-color: #ccc; + color: white!important; +} + +cite, code, tt { + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; + letter-spacing: 0.01em; +} + +tt { + background-color: #f2f2f2; + border-bottom: 1px solid #ddd; + color: #333; +} + +tt.descname, tt.descclassname, tt.xref { + border: 0; +} + +hr { + border: 1px solid #abc; + margin: 2em; +} + +a tt { + border: 0; + color: #CA7900; +} + +a tt:hover { + color: #2491CF; +} + +pre { + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; + letter-spacing: 0.015em; + line-height: 120%; + padding: 0.5em; + border: 1px solid #ccc; + background-color: #f8f8f8; +} + +pre a { + color: inherit; + text-decoration: underline; +} + +td.linenos pre { + padding: 0.5em 0; +} + +div.quotebar { + background-color: #f8f8f8; + max-width: 250px; + float: right; + padding: 2px 7px; + border: 1px solid #ccc; +} + +div.topic { + background-color: #f8f8f8; +} + +table { + border-collapse: collapse; + margin: 0 -0.5em 0 -0.5em; +} + +table td, table th { + padding: 0.2em 0.5em 0.2em 0.5em; +} + +div.admonition, div.warning { + font-size: 0.9em; + margin: 1em 0 1em 0; + border: 1px solid #86989B; + background-color: #f7f7f7; + padding: 0; +} + +div.admonition p, div.warning p { + margin: 0.5em 1em 0.5em 1em; + padding: 0; +} + +div.admonition pre, div.warning pre { + margin: 0.4em 1em 0.4em 1em; +} + +div.admonition p.admonition-title, +div.warning p.admonition-title { + margin: 0; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border-bottom: 1px solid #86989B; + font-weight: bold; + background-color: #AFC1C4; +} + +div.warning { + border: 1px solid #940000; +} + +div.warning p.admonition-title { + background-color: #CF0000; + border-bottom-color: #940000; +} + +div.admonition ul, div.admonition ol, +div.warning ul, div.warning ol { + margin: 0.1em 0.5em 0.5em 3em; + padding: 0; +} + +div.versioninfo { + margin: 1em 0 0 0; + border: 1px solid #ccc; + background-color: #DDEAF0; + padding: 8px; + line-height: 1.3em; + font-size: 0.9em; +} + +.viewcode-back { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', + 'Verdana', sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} diff --git a/doc/advanced/content/_templates/layout.html b/doc/advanced/content/_templates/layout.html index 5603ce5f..0516be55 100644 --- a/doc/advanced/content/_templates/layout.html +++ b/doc/advanced/content/_templates/layout.html @@ -1,8 +1,47 @@ + + + +Documentation - Point Cloud Library (PCL) + {% extends "!layout.html" %} {% block extrahead %} +initialize('web'); + +$snip = $modx->runSnippet("getSiteNavigation", array('id'=>5, 'phLevels'=>'sitenav.level0,sitenav.level1', 'showPageNav'=>'n')); +$chunkOutput = $modx->getChunk("site-header", array('sitenav'=>$snip)); +$bodytag = str_replace("[[+showSubmenus:notempty=`", "", $chunkOutput); +$bodytag = str_replace("`]]", "", $bodytag); +echo $bodytag; +echo "\n"; +?> +
+

Documentation

+ +
+
{% endblock %} +{% block relbar1 %}{% endblock %} +{% block relbar2 %}{% endblock %} {% block rootrellink %}{% endblock %} {% block sidebarsearch %}{% endblock %} + +{% block footer %} +
+ +getChunk("site-footer"); +echo $chunkOutput; +?> +{% endblock %} + + diff --git a/doc/advanced/content/branches_repository.rst b/doc/advanced/content/branches_repository.rst deleted file mode 100644 index 2b5c0c9e..00000000 --- a/doc/advanced/content/branches_repository.rst +++ /dev/null @@ -1,48 +0,0 @@ -.. _branches_repository: - -How to commit concurrently to trunk and branches ------------------------------------------------- - -Most often as a developer you will have to deal with the problem of either applying a commit to a particular branch, or pushing a modification that you just made on your machine to more than one branch. This simple example will show you one of the many ways of doing this. - -The example is given for a piece of code/patch that has to be committed to both **trunk** and one of the **branches** (1.x in this case). - -Before continuing, make sure your code compiles and tests carefully, and follows the indentation guidelines/C++ programming style (see :ref:`pcl_style_guide`). Then, follow this set of simple steps: - - 1. In case you checked out only one of the branches or trunk, go ahead and check out **svn+ssh://svn@svn.pointclouds.org/pcl** instead. As a developer you shouldn't worry too much for the extra space that the tags/branches will consume on your hard drive, but if you do, visit **http://svn.pointclouds.org** and check out all the branches that you want to work on individually. For the former:: - - svn+ssh://svn@svn.pointclouds.org/pcl pcl - - - This will give you both trunk, and all the branches, and tags. - - 2. Assuming that you're working in trunk, go ahead and do the following:: - - - cd pcl/trunk # change directory to where trunk is - svn st -q # check to see what the commit queue contains - svn diff . > /tmp/a.patch # obtain a patch of your code - - At this point */tmp/a.patch* will contain the patch that has to be pushed in the repository. - - 3. Change directory to the branch that you want to commit the same patch to, and do:: - - - cd pcl/branches/pcl-1.x # change directory to where the branch is - patch -p0 < /tmp/a.patch # apply the patch - - - One problem that we will have to deal with now is adding new files that have been added by your patch:: - - svn st # check to see which files have "?" in the branch but should have "A" instead - svn add # add all files that need to be added - - 4. If possible, commit both patches at the same time. Here, we're assuming that branches/pcl-1.x and trunk have the same root directory:: - - cd pcl # change directory to where trunk+branches is - svn st -q - svn commit branches/ trunk/ - - Alternatively, you can perform two individual commits in steps 2 and 3. - - diff --git a/doc/advanced/content/c_cache.rst b/doc/advanced/content/c_cache.rst index fb2864bf..21da47ba 100644 --- a/doc/advanced/content/c_cache.rst +++ b/doc/advanced/content/c_cache.rst @@ -24,7 +24,7 @@ but it actually runs the equivalent of 'ccache g++'. Using colorgcc to colorize output --------------------------------- -`colorgcc`_ is a colorizer for the output +`colorgcc `_ is a colorizer for the output of GCC, and allows you to better interpret the compiler warnings/errors. To enable both colorgcc and ccache, perform the following steps: diff --git a/doc/advanced/content/distcc.rst b/doc/advanced/content/distcc.rst index e254706b..59ce2984 100644 --- a/doc/advanced/content/distcc.rst +++ b/doc/advanced/content/distcc.rst @@ -56,6 +56,11 @@ In each distributed build environment, there are usually two different roles: [pcl] $ mkdir build && cd build [pcl/build] $ CC="distcc gcc" CXX="distcc g++" cmake .. + Sometimes compiling on systems supporting different SSE extensions will lead + to problems. Setting PCL_ENABLE_SSE to false will solve this, like:: + + [pcl/build] $ CC="distcc gcc" CXX="distcc g++" cmake -DPCL_ENABLE_SSE:BOOL=FALSE ../pcl + The output of ``CC="distcc gcc" CXX="distcc g++" cmake ..`` will generate something like this. Please note that this is just an example and that the messages might vary depending on your operating system and the way your diff --git a/doc/advanced/content/files/PCL_eclipse_profile.xml b/doc/advanced/content/files/PCL_eclipse_profile.xml index 25dab64b..5b76b8f2 100644 --- a/doc/advanced/content/files/PCL_eclipse_profile.xml +++ b/doc/advanced/content/files/PCL_eclipse_profile.xml @@ -1,54 +1,54 @@ - + - + - + - + - + - - + + - + - + - - + + - - + + - + @@ -56,102 +56,103 @@ - - + + + - - + + + + - - - - + + - + - + - + - - + + - - + + - - + + - + - + - - + + - + - - + + - + - - + + - - - + + + - + diff --git a/doc/advanced/content/how_to_write_a_tutorial.rst b/doc/advanced/content/how_to_write_a_tutorial.rst index 9437a731..4b1f5b1b 100644 --- a/doc/advanced/content/how_to_write_a_tutorial.rst +++ b/doc/advanced/content/how_to_write_a_tutorial.rst @@ -25,8 +25,8 @@ beautiful HTML documents. Both documentation sources are stored in our `Source repository -`_ and the web pages are generated hourly by -our server via `crontab` jobs. +`_ and the web pages are generated +hourly by our server via `crontab` jobs. In the next two sections we will address both of the above, and present a small example for each. We'll begin with the easiest of the two: adding a new @@ -44,12 +44,12 @@ you read the following resources: * http://www.siafoo.net/help/reST - has a nice tutorial/set of examples Once you understand how reST works, look over our current set of tutorials for -examples at http://svn.pointclouds.org/pcl/trunk/doc/tutorials/content/. +examples at https://github.com/PointCloudLibrary/pcl/tree/master/doc/tutorials/content. To add a new tutorial, simply create a new file, and send it to us together with the images/videos that you want included in the tutorial. The best way to -do this is to login to http://dev.pointclouds.org, create an issue on the -tracker, and add the new tutorial as an attachement. +do this is to login to https://github.com/PointCloudLibrary/pcl and send it as +a pull request. Improving the API documentation @@ -69,7 +69,7 @@ To help us improve the API documentation, all that you need to do is simply check out the source code of PCL (we recommend trunk if you're going to start editing the sources), like:: - svn co http://svn.pointclouds.org/pcl/trunk pcl + git clone https://github.com/PointCloudLibrary/pcl Then, edit the file containing the function/class that you want to improve the documentation for, say *common/include/pcl/point_cloud.h*, and go to the @@ -81,11 +81,7 @@ element that you want to improve. Let's take *points* for example:: What you have to modify is the Doxygen-style comment starting with /\*\* and ending with \*/. See http://www.doxygen.org for more information. -To send us the modification, please login to http://dev.pointclouds.org, create -an issue on the tracker, and add the output of the following command to the -issue:: - - svn diff common/include/pcl/point_cloud.h +To send us the modification, please send a pull request through Github. Testing the modified API documentation -------------------------------------- diff --git a/doc/advanced/content/index.rst b/doc/advanced/content/index.rst index 7332a08b..99716d5a 100644 --- a/doc/advanced/content/index.rst +++ b/doc/advanced/content/index.rst @@ -65,9 +65,9 @@ development that everyone should follow: .. topic:: Rules - * if you make any commits, please **_add the commit log_** or something similar **_to + * if you make important commits, please **_add the commit log_** or something similar **_to the changelist page_** - (http://dev.pointclouds.org/projects/pcl/wiki/ChangeList); + (https://github.com/PointCloudLibrary/pcl/blob/master/CHANGES.md); * if you change anything in an existing algorithm, **_make sure that there are unit tests_** for it and **_make sure that they pass before you commit_** the code; @@ -92,17 +92,12 @@ development that everyone should follow: Short documentation on how to add new, throw and handle exceptions in PCL. -* :ref:`branches_repository` - - If you're not sure how to best make concurrent commits to the repository to both **trunk**, and any of the existing **branches**, see this example. - - * :ref:`pcl2` An in-depth discussion about the PCL 2.x API can be found here. -Commiting changes to trunk --------------------------- +Commiting changes to the git master +----------------------------------- In order to oversee the commit messages more easier and that the changelist looks homogenous please keep the following format: "* X in @@ (#)" @@ -116,20 +111,10 @@ Improving the PCL documentation documentation and tutorials/examples, please read our short guide on how to start. -.. - Profiling your code +How to build a minimal example +------------------------------ +* :ref:`minimal_example` -Contents --------- - -.. toctree:: - - c_cache - distcc - compiler_optimizations - single_compile_unit - pcl_style_guide - branches_repository - how_to_write_a_tutorial + In case you need help to debug your code, please follow this guidelines to write a minimal example. diff --git a/doc/advanced/content/pcl2.rst b/doc/advanced/content/pcl2.rst index ae5faba3..27a27cd0 100644 --- a/doc/advanced/content/pcl2.rst +++ b/doc/advanced/content/pcl2.rst @@ -41,7 +41,6 @@ Proposals for the 2.x API: * make sure we can access a slice of the data as a *2D image*, thus allowing fast 2D displaying, [u, v] operations, etc * make sure we can access a slice of the data as a subpoint cloud: only certain points are chosen from the main point cloud * implement channels (of a single type!) as data holders, e.g.: - * cloud["xyz"] => gets all 3D x,y,z data * cloud["normals"] => gets all surface normal data * etc @@ -71,7 +70,6 @@ Proposals for the 2.x API: pos_space = ( "float with euclidean 2-norm distance", { "x", "y", "z" }, [[(0.3,0,1.3) , ... , (1.2,3.1,2)], ... , [(1,0.3,1) , ... , (2,0,3.5)] ) color_space = ( "uint8 with rgb distance", { "r", "g", "b" }, [[(0,255,0), ... , (128,255,32)] ... [(12,54,31) ... (255,0,192)]] ) - 1.2 PointTypes ^^^^^^^^^^^^^^ @@ -114,7 +112,7 @@ Anything involving a slice of data should use size_t for indices and not int. E. 1.6 RANSAC ^^^^^^^^^^ - * Renaming the functions and internal variables: everything should be named with _src and _tgt: we have confusing names like indices_ and indices_tgt_ (and no indices_src_), setInputCloud and setInputTarget (duuh, everything is an input, it should be setTarget, setSource), in the code, a sample is named: selection, model_ and samples. getModelCoefficients is confusing with getModel (this one should be getBestSample). + * Renaming the functions and internal variables: everything should be named with _src and _tgt: we have confusing names like \indices_ and \indices_tgt_ (and no \indices_src_), setInputCloud and setInputTarget (duuh, everything is an input, it should be setTarget, setSource), in the code, a sample is named: selection, \model_ and samples. getModelCoefficients is confusing with getModel (this one should be getBestSample). * no const-correctness all over, it's pretty scary: all the get should be const, selectWithinDistance and so on too. * the getModel, getInliers function should not force you to fill a vector: you should just return a const reference to the internal vector: that could allow you to save a useless copy * some private members should be made protected in the sub sac models (like sac_model_registration) so that we can inherit from them. diff --git a/doc/advanced/content/pcl_reg_eval.rst b/doc/advanced/content/pcl_reg_eval.rst index ae1b4cca..9102e4d0 100644 --- a/doc/advanced/content/pcl_reg_eval.rst +++ b/doc/advanced/content/pcl_reg_eval.rst @@ -7,23 +7,23 @@ Data generation =============== - synthetic data - real word data (how to get ground truth?) - - Kinect - - PR2 laser scanner - - SICK laser data - - small range 3D scanner - - mid range 3D scanner (Faro) - - high end 3D scanner (Riegl, Velodyne) + - Kinect + - PR2 laser scanner + - SICK laser data + - small range 3D scanner + - mid range 3D scanner (Faro) + - high end 3D scanner (Riegl, Velodyne) - Point Types - - 2D(?) - - 3D - - RGB + - 2D(?) + - 3D + - RGB - dynamics - - static scans - - scanning while driving (e.g. robots) + - static scans + - scanning while driving (e.g. robots) - size - - room - - building - - outdoor (street) + - room + - building + - outdoor (street) Architecture ============ @@ -41,12 +41,14 @@ ICP ^^^ - how does the algorithm cope with outliers - how are the point pairs evaluated: - - does it use normal or RGB information - - does it weight the pairs differently - - which kind of point pairs are used: - - one-to-one - - one-to-many - - many-to-many + + - does it use normal or RGB information + - does it weight the pairs differently + - which kind of point pairs are used: + + - one-to-one + - one-to-many + - many-to-many Similar Projects ================ diff --git a/doc/advanced/content/pcl_registration.rst b/doc/advanced/content/pcl_registration.rst index c00038b2..9f203a4b 100644 --- a/doc/advanced/content/pcl_registration.rst +++ b/doc/advanced/content/pcl_registration.rst @@ -60,7 +60,7 @@ Graph ^^^^^ This should hold the SLAM graph. I would propose to use Boost::Graph for it, as it allows us to access a lot of algorithms. -.. todo:: +.. note:: define abstract structure. @@ -159,7 +159,7 @@ GraphHandler void addConstraint (Graph &gr, PointCloud &from, PointCloud &to, Pose &pose); } -.. todo:: +.. note:: I'm not sure about this one. diff --git a/doc/advanced/content/pcl_style_guide.rst b/doc/advanced/content/pcl_style_guide.rst index 8869b27e..e3c0a546 100644 --- a/doc/advanced/content/pcl_style_guide.rst +++ b/doc/advanced/content/pcl_style_guide.rst @@ -336,7 +336,7 @@ download it to some known location and then: * open .emacs * add the following before any C/C++ custom hooks -.. code-block:: lisp +:: (load-file "/location/to/pcl-c-style.el") (add-hook 'c-mode-common-hook 'pcl-set-c-style) @@ -350,8 +350,37 @@ You can find a semi-finished config for `Uncrustify `_. +| To add the new formatting style go to: Windows > Preferences > C/C++ > Code Style > Formatter + +| To format portion of codes, select the code and press Ctrl + Shift + F. +| If you want to format the whole code in your project go to the tree and right click on the project: Source > Format. + +Note that the Eclipse formatter style is configured to wrap all arguments in a function, feel free to re-arange the arguments if you feel the need; for example, +this improves readability: + +.. code-block:: cpp + + int + displayPoint (float x, float y, float z, + float r, float g, float b + ); + +This eclipse formatter fails to add a space before brackets when using PCL macros: + +.. code-block:: cpp + + PCL_ERROR("Text\n"); + +should be + +.. code-block:: cpp + + PCL_ERROR ("Text\n"); + +.. note:: + + This style sheet is not perfect, please mention errors on the user mailing list and feel free to patch! 3. Structuring ============== diff --git a/doc/advanced/content/vertical_sse.rst b/doc/advanced/content/vertical_sse.rst index cfb0902c..de4bcab8 100644 --- a/doc/advanced/content/vertical_sse.rst +++ b/doc/advanced/content/vertical_sse.rst @@ -677,9 +677,9 @@ clouds. The point clouds used are: -* `capture000X.pcd `_ -* `table_scene_mug_stereo_textured.pcd `_ -* `table_scene_lms400.pcd `_ +* `capture000X.pcd `_ +* `table_scene_mug_stereo_textured.pcd `_ +* `table_scene_lms400.pcd `_ ``capture0001.pcd`` (organized, 640x480, 57553 NaNs):: diff --git a/doc/doxygen/CMakeLists.txt b/doc/doxygen/CMakeLists.txt index 1ec72af1..f4660ffe 100644 --- a/doc/doxygen/CMakeLists.txt +++ b/doc/doxygen/CMakeLists.txt @@ -1,5 +1,13 @@ +if(WITH_DOCS) + find_package(Doxygen) + if(DOXYGEN_FOUND) + find_package(HTMLHelp) + endif(DOXYGEN_FOUND) +endif(WITH_DOCS) + message(STATUS "DOXYGEN_FOUND ${DOXYGEN_FOUND}") message(STATUS "HTML_HELP_COMPILER ${HTML_HELP_COMPILER}") + if(DOXYGEN_FOUND) if(HTML_HELP_COMPILER) set(DOCUMENTATION_HTML_HELP YES) @@ -12,15 +20,22 @@ if(DOXYGEN_FOUND) set(HAVE_DOT NO) endif(DOXYGEN_DOT_EXECUTABLE) + option(DOXYGEN_USE_SHORT_NAMES "Generate shorter (but less readable) file names" OFF) + if(DOXYGEN_USE_SHORT_NAMES) + set(SHORT_NAMES YES) + else(DOXYGEN_USE_SHORT_NAMES) + set(SHORT_NAMES NO) + endif(DOXYGEN_USE_SHORT_NAMES) + set(STRIPPED_HEADERS "${PCL_SOURCE_DIR}/${PCL_MODULES_NAMES}/include") string(REPLACE ";" "/include \\\n\t\t\t\t\t\t\t\t\t\t\t\t ${PCL_SOURCE_DIR}/" STRIPPED_HEADERS "${STRIPPED_HEADERS}") set(DOC_SOURCE_DIR "\"${PCL_SOURCE_DIR}\"\\") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html") set(doxyfile "${CMAKE_CURRENT_BINARY_DIR}/doxyfile") - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doxyfile.in" ${doxyfile}) - add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${doxyfile}) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doxyfile.in" "${doxyfile}") + add_custom_target(doc ALL "${DOXYGEN_EXECUTABLE}" "${doxyfile}") if(USE_PROJECT_FOLDERS) - set_target_properties(doc PROPERTIES FOLDER "Documentation") + set_target_properties(doc PROPERTIES FOLDER "Documentation (Doxygen)") endif(USE_PROJECT_FOLDERS) if(DOCUMENTATION_HTML_HELP STREQUAL YES) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" diff --git a/doc/doxygen/doxyfile.in b/doc/doxygen/doxyfile.in index e96587ff..a51b59d4 100644 --- a/doc/doxygen/doxyfile.in +++ b/doc/doxygen/doxyfile.in @@ -27,7 +27,7 @@ INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = @STRIPPED_HEADERS@ -SHORT_NAMES = YES +SHORT_NAMES = @SHORT_NAMES@ JAVADOC_AUTOBRIEF = YES QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO @@ -51,7 +51,6 @@ SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = NO -SYMBOL_CACHE_SIZE = 0 LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- @@ -88,7 +87,6 @@ ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = NO -SHOW_DIRECTORIES = NO SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = "@PCL_SOURCE_DIR@/doc/doxygen/doxygen_layout.xml" @@ -115,8 +113,7 @@ FILE_PATTERNS = *.h \ *.hpp \ *.doxy RECURSIVE = YES -EXCLUDE = */.svn \ - "@PCL_SOURCE_DIR@/cmake" \ +EXCLUDE = "@PCL_SOURCE_DIR@/cmake" \ "@PCL_SOURCE_DIR@/3rdparty" \ "@PCL_SOURCE_DIR@/test" \ "@PCL_SOURCE_DIR@/android" \ @@ -169,9 +166,9 @@ HTML_HEADER = HTML_FOOTER = @PCL_SOURCE_DIR@/doc/doxygen/footer.html HTML_STYLESHEET = HTML_EXTRA_FILES = -HTML_COLORSTYLE_HUE = 220 -HTML_COLORSTYLE_SAT = 100 -HTML_COLORSTYLE_GAMMA = 80 +HTML_COLORSTYLE_HUE = 87 +HTML_COLORSTYLE_SAT = 46 +HTML_COLORSTYLE_GAMMA = 73 HTML_TIMESTAMP = YES HTML_DYNAMIC_SECTIONS = YES GENERATE_DOCSET = YES @@ -277,9 +274,10 @@ EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = *.h -#PREDEFINED = protected=private \ -PREDEFINED = "HAVE_QHULL=1" \ - "HAVE_OPENNI=1" +#PREDEFINED = protected=private \ +PREDEFINED = = "HAVE_QHULL=1" \ + "HAVE_OPENNI=1" \ + "PCL_DEPRECATED(x)=" EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES diff --git a/doc/doxygen/doxygen_layout.xml b/doc/doxygen/doxygen_layout.xml index 5cf6db94..fb664ebe 100644 --- a/doc/doxygen/doxygen_layout.xml +++ b/doc/doxygen/doxygen_layout.xml @@ -18,7 +18,6 @@ - diff --git a/doc/doxygen/pcl.doxy b/doc/doxygen/pcl.doxy index 8f873cce..0e273fff 100644 --- a/doc/doxygen/pcl.doxy +++ b/doc/doxygen/pcl.doxy @@ -29,9 +29,8 @@ Please visit http://www.pointclouds.org for more information.

Quick Links

  • Main website: http://www.pointclouds.org
  • -
  • Developer Zone: http://dev.pointclouds.org
  • -
  • SVN Repository: http://svn.pointclouds.org
  • -
  • Build farm: http://build.pointclouds.org
  • +
  • Developer Zone: https://github.com/PointCloudLibrary
  • +
  • Build farm: https://travis-ci.org/PointCloudLibrary/pcl

References

diff --git a/doc/overview/Makefile b/doc/overview/Makefile deleted file mode 100644 index 46fe7754..00000000 --- a/doc/overview/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -.PHONY: html - -html: - -rm -rf html /tmp/doctrees - sphinx-build -b html -a -d /tmp/doctrees content html - diff --git a/doc/overview/content/_templates/layout.html b/doc/overview/content/_templates/layout.html deleted file mode 100644 index 5603ce5f..00000000 --- a/doc/overview/content/_templates/layout.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "!layout.html" %} - -{% block extrahead %} -{% endblock %} - -{% block rootrellink %}{% endblock %} - -{% block sidebarsearch %}{% endblock %} diff --git a/doc/overview/content/conf.py b/doc/overview/content/conf.py deleted file mode 100644 index 3c6ae9e2..00000000 --- a/doc/overview/content/conf.py +++ /dev/null @@ -1,135 +0,0 @@ -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# -- General configuration ----------------------------------------------------- -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'PCL' -copyright = '' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '0.0' -# The full version, including alpha/beta/rc tags. -release = '0.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = False - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'sphinxdoc' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = { 'rightsidebar' : 'true' } - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['.'] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -html_short_title = 'Home' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# If false, no module index is generated. -html_use_modindex = False - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -html_split_index = False - -# If true, links to the reST sources are added to the pages. -html_show_sourcelink = False - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -html_file_suffix = '.html' - -html_sidebars = { - '**': [], - 'using/windows': [], -} -html_show_copyright = False -html_show_sphinx = False -html_add_permalinks = None -needs_sphinx = 1.0 -file_insertion_enabled = True -raw_enabled = True - diff --git a/doc/overview/content/index.rst b/doc/overview/content/index.rst deleted file mode 100644 index a3db1caf..00000000 --- a/doc/overview/content/index.rst +++ /dev/null @@ -1,35 +0,0 @@ -.. toctree:: - -Overview --------- - -PCL presents an advanced and extensive approach to the subject of 3D -perception, and it's meant to provide support for all the common 3D building -blocks that applications need. Written from a perspective of online sensor data -processing, PCL deals with point cloud data acquired from real sensing devices -including laser scanners, stereo cameras, and TOF cameras. - -PCL is a fully templated, modern C++ library, with efficient backends for -modern CPUs (SSE optimized), and GPUs (CUDA). The plethora of state-of-the-art -algorithms implemented is large, with many new ones added on a weekly to -monthly basis -- acquisition, filtering, feature estimation, surface -reconstruction, registration, model fitting, and segmentation, are just a few -of the many topics covered by PCL. - -The project is supported by an international community of robotics and perception -researchers, and would not exist without the contributions of many people and -companies. We thank everyone for their support! - -Presentation ------------- - -The following overview presentation was given at the ROS Fall School at TUM in -November 2010. - -.. raw:: html - -

- - (download here) -

- diff --git a/doc/tutorials/CMakeLists.txt b/doc/tutorials/CMakeLists.txt index 0d3d98dc..b1efe963 100644 --- a/doc/tutorials/CMakeLists.txt +++ b/doc/tutorials/CMakeLists.txt @@ -1,24 +1,14 @@ -find_package(Sphinx) if(SPHINX_FOUND) - file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html") - if(WIN32) - set(TMPDIR "$ENV{TEMP}") - else() - set(TMPDIR "/tmp") - endif() - file(TO_CMAKE_PATH "${TMPDIR}" TMPDIR) - add_custom_target(Tutorials - COMMAND ${CMAKE_COMMAND} -E remove_directory "${TMPDIR}/doctrees" - COMMAND ${SPHINX_EXECUTABLE} -b html -a -d "${TMPDIR}/doctrees" "${CMAKE_CURRENT_SOURCE_DIR}/content" html - ) + add_custom_target(tutorials ALL + COMMAND "${SPHINX_EXECUTABLE}" -b html -a -d "${SPHINX_CACHE_DIR}" -D html_file_suffix=".${SPHINX_HTML_FILE_SUFFIX}" "${CMAKE_CURRENT_SOURCE_DIR}/content" html) + add_dependencies(tutorials doc) if(USE_PROJECT_FOLDERS) - set_target_properties(Tutorials PROPERTIES FOLDER "Documentation") + set_target_properties(tutorials PROPERTIES FOLDER "Documentation (Tutorials)") endif(USE_PROJECT_FOLDERS) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" DESTINATION "${DOC_INSTALL_DIR}/tutorials" COMPONENT doc) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/content/sources" DESTINATION "${DOC_INSTALL_DIR}/tutorials" - COMPONENT doc - PATTERN ".svn" EXCLUDE) + COMPONENT doc) endif(SPHINX_FOUND) diff --git a/doc/tutorials/Makefile b/doc/tutorials/Makefile deleted file mode 100644 index 46fe7754..00000000 --- a/doc/tutorials/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -.PHONY: html - -html: - -rm -rf html /tmp/doctrees - sphinx-build -b html -a -d /tmp/doctrees content html - diff --git a/doc/tutorials/content/_static/basic.css b/doc/tutorials/content/_static/basic.css new file mode 100644 index 00000000..efe60182 --- /dev/null +++ b/doc/tutorials/content/_static/basic.css @@ -0,0 +1,538 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +img { + border: 0; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { +font-family: "Droid Serif", "DejaVu Serif", "Garamond", serif; +font-size: 1.3em; +color: #64794c; +margin-bottom: 0; + margin-top: 0 !important; +} + +.first img { +max-width: none !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + clear: both; + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.refcount { + color: #060; +} + +.optional { + font-size: 1.3em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +white-space : pre-wrap; /*for Mozilla*/ +word-wrap: break-word; /*for IE*/ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +tt.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +tt.descclassname { + background-color: transparent; +} + +tt.xref, a tt { + background-color: transparent; + font-weight: bold; +} + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} diff --git a/doc/tutorials/content/_static/sphinxdoc.css b/doc/tutorials/content/_static/sphinxdoc.css new file mode 100644 index 00000000..62ff7fd6 --- /dev/null +++ b/doc/tutorials/content/_static/sphinxdoc.css @@ -0,0 +1,315 @@ +/* + * sphinxdoc.css_t + * ~~~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- sphinxdoc theme. Originally created by + * Armin Ronacher for Werkzeug. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + color: black; + padding: 0; + margin: 0px 80px 0px 80px; + min-width: 740px; +} + +div.document { + + text-align: left; + + +} + +div.bodywrapper { + margin: 0 240px 0 0; + border-right: 1px solid #ccc; +} + +div.body { + margin: 0; + padding: 0.5em 20px 20px 20px; +} + +div.related { + font-size: 1em; +} + +div.related ul { + background-image: url(navigation.png); + height: 2em; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} + +div.related ul li { + margin: 0; + padding: 0; + height: 2em; + float: left; +} + +div.related ul li.right { + float: right; + margin-right: 5px; +} + +div.related ul li a { + margin: 0; + padding: 0 5px 0 5px; + line-height: 1.75em; + color: #EE9816; +} + +div.related ul li a:hover { + color: #3CA8E7; +} + +div.sphinxsidebarwrapper { + padding: 0; +} + +div.sphinxsidebar { + margin: 0; + padding: 0.5em 15px 15px 0; + width: 210px; + float: right; + font-size: 1em; + text-align: left; +} + +div.sphinxsidebar h3, div.sphinxsidebar h4 { + margin: 1em 0 0.5em 0; + font-size: 1em; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border: 1px solid #86989B; + background-color: #AFC1C4; +} + +div.sphinxsidebar h3 a { + color: white; +} + +div.sphinxsidebar ul { + padding-left: 1.5em; + margin-top: 7px; + padding: 0; + line-height: 130%; +} + +div.sphinxsidebar ul ul { + margin-left: 20px; +} + +div.footer { + background-color: #E3EFF1; + color: #86989B; + padding: 3px 8px 3px 0; + clear: both; + font-size: 0.8em; + text-align: right; +} + +div.footer a { + color: #86989B; + text-decoration: underline; +} + +/* -- body styles ----------------------------------------------------------- */ + +p { + margin: 0.8em 0 0.5em 0; +} + +div.body a { + text-decoration: underline; +} + +h2 { +/* color: #11557C;*/ + margin: 1.3em 0 0.2em 0; + font-size: 1.35em; + padding: 0; +} + +h3 { + margin: 1em 0 -0.3em 0; + font-size: 1.2em; +} + +div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a { + color: black!important; +} + +h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { + display: none; + margin: 0 0 0 0.3em; + padding: 0 0.2em 0 0.2em; + color: #aaa!important; +} + +h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, +h5:hover a.anchor, h6:hover a.anchor { + display: inline; +} + +h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, +h5 a.anchor:hover, h6 a.anchor:hover { + color: #777; + background-color: #eee; +} + +a.headerlink { + color: #c60f0f!important; + font-size: 1em; + margin-left: 6px; + padding: 0 4px 0 4px; + text-decoration: none!important; +} + +a.headerlink:hover { + background-color: #ccc; + color: white!important; +} + +cite, code, tt { + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; + letter-spacing: 0.01em; +} + +tt { + background-color: #f2f2f2; + border-bottom: 1px solid #ddd; + color: #333; +} + +tt.descname, tt.descclassname, tt.xref { + border: 0; +} + +hr { + border: 1px solid #abc; + margin: 2em; +} + +a tt { + border: 0; + color: #CA7900; +} + +a tt:hover { + color: #2491CF; +} + +pre { + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; + letter-spacing: 0.015em; + line-height: 120%; + padding: 0.5em; + border: 1px solid #ccc; + background-color: #f8f8f8; +} + +pre a { + color: inherit; + text-decoration: underline; +} + +td.linenos pre { + padding: 0.5em 0; +} + +div.quotebar { + background-color: #f8f8f8; + max-width: 250px; + float: right; + padding: 2px 7px; + border: 1px solid #ccc; +} + +div.topic { + background-color: #f8f8f8; +} + +table { + border-collapse: collapse; + margin: 0 -0.5em 0 -0.5em; +} + +table td, table th { + padding: 0.2em 0.5em 0.2em 0.5em; +} + +div.admonition, div.warning { + font-size: 0.9em; + margin: 1em 0 1em 0; + border: 1px solid #86989B; + background-color: #f7f7f7; + padding: 0; +} + +div.admonition p, div.warning p { + margin: 0.5em 1em 0.5em 1em; + padding: 0; +} + +div.admonition pre, div.warning pre { + margin: 0.4em 1em 0.4em 1em; +} + +div.admonition p.admonition-title, +div.warning p.admonition-title { + margin: 0; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border-bottom: 1px solid #86989B; + font-weight: bold; + background-color: #AFC1C4; +} + +div.warning { + border: 1px solid #940000; +} + +div.warning p.admonition-title { + background-color: #CF0000; + border-bottom-color: #940000; +} + +div.admonition ul, div.admonition ol, +div.warning ul, div.warning ol { + margin: 0.1em 0.5em 0.5em 3em; + padding: 0; +} + +div.versioninfo { + margin: 1em 0 0 0; + border: 1px solid #ccc; + background-color: #DDEAF0; + padding: 8px; + line-height: 1.3em; + font-size: 0.9em; +} + +.viewcode-back { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', + 'Verdana', sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} diff --git a/doc/tutorials/content/_templates/layout.html b/doc/tutorials/content/_templates/layout.html index 5603ce5f..0516be55 100644 --- a/doc/tutorials/content/_templates/layout.html +++ b/doc/tutorials/content/_templates/layout.html @@ -1,8 +1,47 @@ + + + +Documentation - Point Cloud Library (PCL) + {% extends "!layout.html" %} {% block extrahead %} +initialize('web'); + +$snip = $modx->runSnippet("getSiteNavigation", array('id'=>5, 'phLevels'=>'sitenav.level0,sitenav.level1', 'showPageNav'=>'n')); +$chunkOutput = $modx->getChunk("site-header", array('sitenav'=>$snip)); +$bodytag = str_replace("[[+showSubmenus:notempty=`", "", $chunkOutput); +$bodytag = str_replace("`]]", "", $bodytag); +echo $bodytag; +echo "\n"; +?> +
+

Documentation

+ +
+
{% endblock %} +{% block relbar1 %}{% endblock %} +{% block relbar2 %}{% endblock %} {% block rootrellink %}{% endblock %} {% block sidebarsearch %}{% endblock %} + +{% block footer %} +
+ +getChunk("site-footer"); +echo $chunkOutput; +?> +{% endblock %} + + diff --git a/doc/tutorials/content/adding_custom_ptype.rst b/doc/tutorials/content/adding_custom_ptype.rst index 46de5606..51914fea 100644 --- a/doc/tutorials/content/adding_custom_ptype.rst +++ b/doc/tutorials/content/adding_custom_ptype.rst @@ -64,7 +64,7 @@ What `PointT` types are available in PCL? To cover all possible cases that we could think of, we defined a plethora of point types in PCL. The following might be only a snippet, please see -`point_types.hpp `_ +`point_types.hpp `_ for the complete list. This list is important, because before defining your own custom type, you need @@ -807,8 +807,8 @@ make sense to try to use explicit instantiations for your `MyPointType` types, for any classes that you expose (from PCL our outside PCL). .. note:: -Starting with PCL-1.7 you need to define PCL_NO_PRECOMPILE before you include -any PCL headers to include the templated algorithms as well. + Starting with PCL-1.7 you need to define PCL_NO_PRECOMPILE before you include + any PCL headers to include the templated algorithms as well. Example ------- diff --git a/doc/tutorials/content/alignment_prerejective.rst b/doc/tutorials/content/alignment_prerejective.rst index 98bc8459..ddfad3f0 100644 --- a/doc/tutorials/content/alignment_prerejective.rst +++ b/doc/tutorials/content/alignment_prerejective.rst @@ -9,7 +9,7 @@ In this tutorial, we show how to find the alignment pose of a rigid object in a The code -------- -First, download the datasets from :download:`here <./sources/alignment_prerejective/data/alignment_prerejective.tar.gz>` and extract the files. +First, download the test models: :download:`object <./sources/alignment_prerejective/chef.pcd>` and :download:`scene <./sources/alignment_prerejective/rs1.pcd>`. Next, copy and paste the following code into your editor and save it as ``alignment_prerejective.cpp`` (or download the source file :download:`here <./sources/alignment_prerejective/alignment_prerejective.cpp>`). @@ -54,27 +54,27 @@ We are now ready to setup the alignment process. We use the class :pcl:`SampleCo .. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp :language: cpp - :lines: 79-90 + :lines: 79-91 .. note:: Apart from the usual input point clouds and features, this class takes some additional runtime parameters which have great influence on the performance of the alignment algorithm. The first two have the same meaning as in the alignment class :pcl:`SampleConsensusInitialAlignment `: - Number of samples - *setNumberOfSamples ()*: The number of point correspondences to sample between the object and the scene. At minimum, 3 points are required to calculate a pose. - Correspondence randomness - *setCorrespondenceRandomness ()*: Instead of matching each object FPFH descriptor to its nearest matching feature in the scene, we can choose between the *N* best matches at random. This increases the iterations necessary, but also makes the algorithm robust towards outlier matches. - - Polygonal similarity threshold - *setSimlarityThreshold ()*: The alignment class uses the :pcl:`CorrespondenceRejectorPoly ` class for early elimination of bad poses based on pose-invariant geometric consistencies of the inter-distances between sampled points on the object and the scene. The closer this value is set to 1, the more greedy and thereby fast the algorithm becomes. However, this also increases the risk of eliminating good poses when noise is present. + - Polygonal similarity threshold - *setSimilarityThreshold ()*: The alignment class uses the :pcl:`CorrespondenceRejectorPoly ` class for early elimination of bad poses based on pose-invariant geometric consistencies of the inter-distances between sampled points on the object and the scene. The closer this value is set to 1, the more greedy and thereby fast the algorithm becomes. However, this also increases the risk of eliminating good poses when noise is present. - Inlier threshold - *setMaxCorrespondenceDistance ()*: This is the Euclidean distance threshold used for determining whether a transformed object point is correctly aligned to the nearest scene point or not. In this example, we have used a heuristic value of 1.5 times the point cloud resolution. - - Inlier fraction - *setInlierFraction ()*: In many practical scenarios, large parts of the observed object in the scene are not visible, either due to clutter, occlusions or both. In such cases, we need to allow for pose hypotheses that do not align all object points to the scene. The absolute number of correctly aligned points is determined using the inlier threshold, and if the ratio of this number to the total number of points in the object is higher than the specified inlier fraction, we accept a pose hypothesis as valid. Furthermore, if a pose generates the highest number of inliers so far, the pose is stored as the current output. In other words, this class tries to maximize the inliers instead of minimizing the fit error during the alignment process. + - Inlier fraction - *setInlierFraction ()*: In many practical scenarios, large parts of the observed object in the scene are not visible, either due to clutter, occlusions or both. In such cases, we need to allow for pose hypotheses that do not align all object points to the scene. The absolute number of correctly aligned points is determined using the inlier threshold, and if the ratio of this number to the total number of points in the object is higher than the specified inlier fraction, we accept a pose hypothesis as valid. Finally, we are ready to execute the alignment process. .. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp :language: cpp - :lines: 91 + :lines: 92-95 The aligned object is stored in the point cloud *object_aligned*. If a pose with enough inliers was found (more than 25 % of the total number of object points), the algorithm is said to converge, and we can print and visualize the results. .. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp :language: cpp - :lines: 95-109 + :lines: 99-114 Compiling and running the program @@ -91,14 +91,16 @@ After you have made the executable, you can run it like so:: $ ./alignment_prerejective chef.pcd rs1.pcd After a few seconds, you will see a visualization and a terminal output similar to:: - - | -0.003 -0.972 0.235 | - R = | -0.993 -0.026 -0.119 | - | 0.122 -0.233 -0.965 | - t = < 0.095, -0.022, 0.069 > + Alignment took 352ms. - Inliers: 890/3432 + | 0.040 -0.929 -0.369 | + R = | -0.999 -0.035 -0.020 | + | 0.006 0.369 -0.929 | + + t = < -0.287, 0.045, 0.126 > + + Inliers: 987/3432 The visualization window should look something like the below figures. The scene is shown with green color, and the aligned object model is shown with blue color. Note the high number of non-visible object points. diff --git a/doc/tutorials/content/bspline_fitting.rst b/doc/tutorials/content/bspline_fitting.rst new file mode 100644 index 00000000..518261ed --- /dev/null +++ b/doc/tutorials/content/bspline_fitting.rst @@ -0,0 +1,278 @@ +.. _bspline_fitting: + +Fitting trimmed B-splines to unordered point clouds +--------------------------------------------------- + +This tutorial explains how to run a B-spline fitting algorithm on a +point-cloud, to obtain a smooth, parametric surface representation. +The algorithm consists of the following steps: + +* Initialization of the B-spline surface by using the Principal Component Analysis (PCA). This + assumes that the point-cloud has two main orientations, i.e. that it is roughly planar. + +* Refinement and fitting of the B-spline surface. + +* Circular initialization of the B-spline curve. Here we assume that the point-cloud is + compact, i.e. no separated clusters. + +* Fitting of the B-spline curve. + +* Triangulation of the trimmed B-spline surface. + +In this video, the algorithm is applied to the frontal scan of the stanford bunny (204800 points): + +.. raw:: html + + + + +Theoretical background +---------------------- + +Theoretical information on the algorithm can be found in this `report +`_ and in my `PhD thesis +`_. + + +PCL installation settings +------------------------- + +Please note that the modules for NURBS and B-splines are not enabled by default. +Make sure you enable "BUILD_surface_on_nurbs" in your ccmake configuration, by setting it to ON. + +If your license permits, also enable "USE_UMFPACK" for sparse linear solving. +This requires SuiteSparse (libsuitesparse-dev in Ubuntu) which is faster, +allows more degrees of freedom (i.e. control points) and more data points. + +The program created during this tutorial is available in +*pcl/examples/surface/example_nurbs_fitting_surface.cpp* and is built when +"BUILD_examples" is set to ON. This will create the binary called *pcl_example_nurbs_fitting_surface* +in your *bin* folder. + + +The code +-------- + +The cpp file used in this tutorial can be found in *pcl/doc/tutorials/content/sources/bspline_fitting/bspline_fitting.cpp*. +You can find the input file at *pcl/test/bunny.pcd*. + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :linenos: + :lines: 1-220 + + +The explanation +--------------- +Now, let's break down the code piece by piece. +Lets start with the choice of the parameters for B-spline surface fitting: + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :linenos: + :lines: 56-66 + +* *order* is the polynomial order of the B-spline surface. + +* *refinement* is the number of refinement iterations, where for each iteration control-points + are inserted, approximately doubling the control points in each parametric direction + of the B-spline surface. + +* *iterations* is the number of iterations that are performed after refinement is completed. + +* *mesh_resolution* the number of vertices in each parametric direction, + used for triangulation of the B-spline surface. + +Fitting: + +* *interior_smoothness* is the smoothness of the surface interior. + +* *interior_weight* is the weight for optimization for the surface interior. + +* *boundary_smoothness* is the smoothness of the surface boundary. + +* *boundary_weight* is the weight for optimization for the surface boundary. + +Note, that the boundary in this case is not the trimming curve used later on. +The boundary can be used when a point-set exists that defines the boundary. Those points +can be declared in *pcl::on_nurbs::NurbsDataSurface::boundary*. In that case, when the +*boundary_weight* is greater than 0.0, the algorithm tries to align the domain boundaries +to these points. In our example we are trimming the surface anyway, so there is no need +for aligning the boundary. + +Initialization of the B-spline surface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 68-72 + +The command *initNurbsPCABoundingBox* uses PCA to create a coordinate systems, where the principal +eigenvectors point into the direction of the maximum, middle and minimum extension of the point-cloud. +The center of the coordinate system is located at the mean of the points. +To estimate the extension of the B-spline surface domain, a bounding box is computed in the plane formed +by the maximum and middle eigenvectors. That bounding box is used to initialize the B-spline surface with +its minimum number of control points, according to the polynomial degree chosen. + +The surface fitting class *pcl::on_nurbs::FittingSurface* is initialized with the point data and the initial +B-spline. + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 74-80 + +The *on_nurbs::Triangulation* class allows easy conversion between the *ON_NurbsSurface* and the *PolygonMesh* class, +for visualization of the B-spline surfaces. Note that NURBS are a generalization of B-splines, +and are therefore a valid container for B-splines, with all control-point weights = 1. + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 82-92 + +Refinement and fitting of the B-spline surface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +At this point of the code we have a B-spline surface with minimal number of control points. +Typically they are not enough to represent finer details of the underlying geometry +of the point-cloud. However, if we increase the control-points to our desired level of detail and +subsequently fit the refined B-spline, we run into problems. For robust fitting B-spline surfaces +the rule is: +"The higher the degree of freedom of the B-spline surface, the closer we have to be to the points to be approximated". + +This is the reason why we iteratively increase the degree of freedom by refinement in both directions (line 85-86), +and fit the B-spline surface to the point-cloud, getting closer to the final solution. + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 94-102 + +After we reached the final level of refinement, the surface is further fitted to the point-cloud +for a pleasing end result. + +Initialization of the B-spline curve +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now that we have the surface fitted to the point-cloud, we want to cut off the overlapping regions of the surface. +To achieve this we project the point-cloud into the parametric domain using the closest points to the B-spline surface. +In this domain of R^2 we perform the weighted B-spline curve fitting, that creates a closed trimming curve that approximately +contains all the points. + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 107-120 + +The topic of curve fitting goes a bit deeper into the thematics of B-splines. Here we assume that you are +familiar with the concept of B-splines, knot vectors, control-points, and so forth. +Please consider the curve being split into supporting regions which is bound by consecutive knots. +Also note that points that are inside and outside the curve are distinguished. + +* *addCPsAccuracy* the distance of the supporting region of the curve to the closest data points has to be below + this value, otherwise a control point is inserted. + +* *addCPsIteration* inner iterations without inserting control points. + +* *maxCPs* the maximum total number of control-points. + +* *accuracy* the average fitting accuracy of the curve, w.r.t. the supporting regions. + +* *iterations* maximum number of iterations performed. + +* *closest_point_resolution* number of control points that must lie within each supporting region. (0 turns this constraint off) + +* *closest_point_weight* weight for fitting the curve to its closest points. + +* *closest_point_sigma2* threshold for closest points (disregard points that are further away from the curve). + +* *interior_sigma2* threshold for interior points (disregard points that are further away from and lie within the curve). + +* *smooth_concavity* value that leads to inward bending of the curve (0 = no bending; <0 inward bending; >0 outward bending). + +* *smoothness* weight of smoothness term. + + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 122-127 + +The curve is initialized using a minimum number of control points to represent a circle, with the center located +at the mean of the point-cloud and the radius of the maximum distance of a point to the center. +Please note that interior weighting is enabled for all points with the command *curve_data.interior_weight_function.push_back (true)*. + +Fitting of the B-spline curve +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 129-133 + +Similar to the surface fitting approach, the curve is iteratively fitted and refined, as shown in the video. +Note how the curve tends to bend inwards at regions where it is not supported by any points. + +Triangulation of the trimmed B-spline surface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 136-142 + +After the curve fitting terminated, our geometric representation consists of a B-spline surface and a closed +B-spline curved, defined within the parametric domain of the B-spline surface. This is called trimmed B-spline surface. +In line 140 we can use the trimmed B-spline to create a triangular mesh. The triangulation algorithm first triangulates +the whole domain and afterwards removes triangles that lie outside of the trimming curve. Vertices of triangles +that intersect the trimming curve are clamped to the curve. + +When running this example and switch to wire-frame mode (w), you will notice that the triangles are ordered in +a rectangular way, which is a result of the rectangular domain of the surface. + +Some hints +---------- +Please bear in mind that the robustness of this algorithm heavily depends on the underlying data. +The parameters for B-spline fitting are designed to model the characteristics of this data. + +* If you have holes or steps in your data, you might want to work with lower refinement levels and lower accuracy to + prevent the B-spline from folding and twisting. Moderately increasing of the smoothness might also work. + +* Try to introduce as much pre-conditioning and constraints to the parameters. E.g. if you know, that + the trimming curve is rather simple, then limit the number of maximum control points. + +* Start simple! Before giving up on gaining control over twisting and bending B-splines, I highly recommend + to start your fitting trials with a small number of control points (low refinement), + low accuracy but also low smoothness (B-splines have implicit smoothing property). + +Compiling and running the program +--------------------------------- + +Add the following lines to your CMakeLists.txt file: + +.. literalinclude:: sources/bspline_fitting/CMakeLists.txt + :language: cmake + :linenos: + +After you have made the executable, you can run it. Simply do: + + $ ./bspline_fitting ${PCL_ROOT}/test/bunny.pcd + + +Saving and viewing the result +----------------------------- + +* Saving as OpenNURBS (3dm) file + +You can save the B-spline surface by using the commands provided by OpenNurbs: + +.. literalinclude:: sources/bspline_fitting/bspline_fitting.cpp + :language: cpp + :lines: 145-163 + +The files generated can be viewed with the pcl/examples/surface/example_nurbs_viewer_surface.cpp. + +* Saving as triangle mesh into a vtk file + +You can save the triangle mesh for example by saving into a VTK file by: + + #include + ... + pcl::io::saveVTKFile ("mesh.vtk", mesh); + +PCL also provides vtk conversion into other formats (PLY, OBJ). + diff --git a/doc/tutorials/content/building_pcl.rst b/doc/tutorials/content/building_pcl.rst index 06d0f877..f0b8fafc 100644 --- a/doc/tutorials/content/building_pcl.rst +++ b/doc/tutorials/content/building_pcl.rst @@ -36,7 +36,6 @@ Let's have a look at what `cmake` options got enabled:: You should see something like the following on screen:: - BUILD_TESTS ON BUILD_common ON BUILD_features ON BUILD_filters ON @@ -61,8 +60,6 @@ You should see something like the following on screen:: The explanation --------------- -* `BUILD_TESTS`: option to enable/disable building of tests - * `BUILD_common`: option to enable/disable building of common library * `BUILD_features`: option to enable/disable building of features library @@ -110,9 +107,9 @@ Tweaking basic settings Depending on your project/system, you might want to enable/disable certain options. For example, you can prevent the building of: -* tests: setting BUILD_TESTS and BUILD_global_tests to OFF +* tests: setting `BUILD_global_tests` to `OFF` -* a library: setting BUILD_LIBRARY_NAME to OFF +* a library: setting `BUILD_LIBRARY_NAME` to `OFF` Note that if you disable a XXX library that is required for building YYY then XXX will be built but won't appear in the cache. @@ -143,8 +140,26 @@ you have all the dependencies installed. In this section we will discuss each dependency entry so that you can configure/build or update/build PCL according to your system. -General remarks -^^^^^^^^^^^^^^^^ +Building unit tests +^^^^^^^^^^^^^^^^^^^ + +If you want to contribute to PCL, or are modifying the code, you need +to turn on building of unit tests. This is accomplished by setting the `BUILD_global_tests` +option to `ON`, with a few caveats. If you're using `ccmake` and you find that `BUILD_global_tests` +is reverting to `OFF` when you configure, you can move the cursor up to the `BUILD_global_tests` line to see the +error message. + +Two options which will need to be turned ON before `BUILD_global_tests` are `BUILD_outofcore` and +`BUILD_people`. Your mileage may vary. + +Also required for unit tests is the source code for the Google C++ Testing Framework. That is +usually as simple as downloading the source, extracting it, and pointing the `GTEST_SRC_DIR` and `GTEST_INCLUDE_DIR` +options to the applicable source locations. On Ubuntu, you can simply run `apt-get install libgtest-dev`. + +These steps enable the `tests` make target, so you can use `make tests` to run tests. + +General remarks +^^^^^^^^^^^^^^^ Under ${PCL_ROOT}/cmake/Modules there is a list of FindXXX.cmake files used to locate dependencies and set their related variables. They have a list of default searchable paths where to look for them. In addition, diff --git a/doc/tutorials/content/cloud_viewer.rst b/doc/tutorials/content/cloud_viewer.rst index 1b8e634f..939914f9 100644 --- a/doc/tutorials/content/cloud_viewer.rst +++ b/doc/tutorials/content/cloud_viewer.rst @@ -10,7 +10,7 @@ to get you up and viewing clouds in as little code as possible. The CloudViewer class is **NOT** meant to be used in multi-threaded applications! Please check the documentation on - :pcl:`PCLVisualizer` or read the :ref:`pcl_visualizer` tutorial + :pcl:`PCLVisualizer` or read the :ref:`pcl_visualizer` tutorial for thread safe visualization. Simple Cloud Visualization diff --git a/doc/tutorials/content/compiling_pcl_dependencies_windows.rst b/doc/tutorials/content/compiling_pcl_dependencies_windows.rst index fe6fa3e4..f8c4dace 100644 --- a/doc/tutorials/content/compiling_pcl_dependencies_windows.rst +++ b/doc/tutorials/content/compiling_pcl_dependencies_windows.rst @@ -32,7 +32,7 @@ compile a series of 3rd party library dependencies: used as the matrix backend for SSE optimized math. **mandatory** - - **FLANN** version >= 1.6.8 (http://www.cs.ubc.ca/~mariusm/index.php/FLANN/FLANN) + - **FLANN** version >= 1.6.8 (http://www.cs.ubc.ca/research/flann/) used in `kdtree` for fast approximate nearest neighbors search. **mandatory** @@ -52,19 +52,15 @@ compile a series of 3rd party library dependencies: used to grab point clouds from OpenNI compliant devices. **optional** - - **Qt** version >= 4.6 (http://qt.nokia.com/) + - **Qt** version >= 4.6 (http://qt.digia.com/) used for developing applications with a graphical user interface (GUI) **optional** - - **MPI** version >= 1.4 (http://www.mcs.anl.gov/research/projects/mpich2/) - - **optional** - .. note:: Though not a dependency per se, don't forget that you also need the CMake - build system (http://www.cmake.org/), at least version **2.8.3**. A Subversion client for Windows, i.e. TortoiseSVN - (http://tortoisesvn.tigris.org/), is also required to download the PCL source code. + build system (http://www.cmake.org/), at least version **2.8.3**. A Git + client for Windows is also required to download the PCL source code. Building dependencies --------------------- @@ -92,9 +88,6 @@ like:: Let's start with `Boost`. We will be using the `CMake-able Boost` project which provide a CMake based build system for Boost. - As a dependency of MPI Boost module (optional), you need first to download and install MPI from the link above. Choose "Win IA32 binary" - if you are building 32 bit PCL libraries, or "Win X86_64 binary" if you are building 64 bit binaries. - If you do not need it, you can skip this, and remove "mpi" from the modules list later. To build Boost, open the CMake-gui and fill in the fields:: @@ -142,20 +135,19 @@ like:: then fill the **BUILD_PROJECTS** CMake entry (which is set to `ALL` by default) with a semicolon-seperated list of boost modules:: - BUILD_PROJECTS : system;filesystem;date_time;thread;iostreams;tr1;serialization;mpi + BUILD_PROJECTS : system;filesystem;date_time;thread;iostreams;tr1;serialization Also, uncheck the **ENABLE_STATIC_RUNTIME** checkbox. Then, click "Configure" again. If you get some errors related to Python, then uncheck **WITH_PYTHON** checkbox, and click "Configure" again. Now, in the CMake log, you should see something like:: Reading boost project directories (per BUILD_PROJECTS) - + + date_time + thread + serialization + system + filesystem - + mpi +-- optional python bindings disabled since PYTHON_FOUND is false. + tr1 @@ -165,20 +157,6 @@ like:: in the solution file, and then will install the build libraries along with the header files to the default installation folder (e.g. C:/Program Files (x86)/Boost). - .. note:: - - If you are building the mpi boost module, and you are using CMake <= 2.8.7, you may run into the following error:: - - LINK : fatal error LNK1104: cannot open file 'C:\Program Files\MPICH2\lib\mpi.lib C:\Program Files\MPICH2\lib\cxx.lib' - - As a workaround (until CMake 2.8.8 is out), go back to CMake gui, check the "Advanced" checkbox at the top right of - CMake window, and edit these entries as follows (please adjust the paths according to your system):: - - MPI_CXX_LIBRARIES : C:/Program Files/MPICH2/lib/cxx.lib;C:/Program Files/MPICH2/lib/mpi.lib - MPI_LIBRARY : C:/Program Files/MPICH2/lib/mpi.lib - - Then, click "Generate". Visual Studio will ask you to reload the solution, then re build the **INSTALL** project. - .. note:: If you get some errors during the installation process, it could be caused by the UAC of MS Windows @@ -221,7 +199,7 @@ like:: If you don't have a Python interpreter installed CMake would probably not allow you to generate the project files. To solve this problem you can install the Python interpreter - (http://www.python.org/download/windows/) or comment the `add_subdirectory( test )` line + (https://www.python.org/download/windows/) or comment the `add_subdirectory( test )` line from C:/PCL_dependencies/flann-1.7.1-src/CMakeLists.txt . - **QHull** : diff --git a/doc/tutorials/content/compiling_pcl_macosx.rst b/doc/tutorials/content/compiling_pcl_macosx.rst index 9c3da398..cecaceb6 100644 --- a/doc/tutorials/content/compiling_pcl_macosx.rst +++ b/doc/tutorials/content/compiling_pcl_macosx.rst @@ -20,7 +20,7 @@ Prerequisites Before getting started download and install the following prerequisites for Mac OS X: -- **XCode** (http://developer.apple.com/xcode) +- **XCode** (https://developer.apple.com/xcode/) Apple’s powerful integrated development environment @@ -60,7 +60,7 @@ The following libraries are **Required** to build PCL. Unified matrix library. Used as the matrix backend for SSE optimized math. - **FLANN** version >= 1.6.8 - (http://www.cs.ubc.ca/~mariusm/index.php/FLANN/FLANN) + (http://www.cs.ubc.ca/research/flann/) Library for performing fast approximate nearest neighbor searches in high dimensional spaces. Used in `kdtree` for fast approximate nearest neighbors search. @@ -104,7 +104,7 @@ for PCL developers: A documentation system for C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), Fortran, VHDL, PHP, C#, and to some extent D. -- **Sphinx** (http://sphinx.pocoo.org/) +- **Sphinx** (http://sphinx-doc.org/) A tool that makes it easy to create intelligent and beautiful documentation. @@ -235,9 +235,9 @@ Building PCL At this point you should have everything needed installed to build PCL with almost no additional configuration. -Checkout the PCL source from the trunk:: +Checkout the PCL source from the Github: - $ svn co http://svn.pointclouds.org/pcl/trunk pcl + $ git clone https://github.com/PointCloudLibrary/pcl $ cd pcl Create the build directories, configure CMake, build and install:: @@ -292,7 +292,7 @@ using Sphinx. The easiest way to get this installed is using pythons $ easy_install -U Sphinx The Sphinx documentation also requires the third party contrib extension -`sphinxcontrib-doxylink` (http://pypi.python.org/pypi/sphinxcontrib-doxylink) +`sphinxcontrib-doxylink` (https://pypi.python.org/pypi/sphinxcontrib-doxylink) to reference the Doxygen built documentation. To install from source you'll also need Mercurial:: diff --git a/doc/tutorials/content/compiling_pcl_windows.rst b/doc/tutorials/content/compiling_pcl_windows.rst index bf906ae7..f3d7dcc4 100644 --- a/doc/tutorials/content/compiling_pcl_windows.rst +++ b/doc/tutorials/content/compiling_pcl_windows.rst @@ -65,9 +65,8 @@ is needed only to build PCL tests. We do not provide GTest installers. **optiona .. note:: Though not a dependency per se, don't forget that you also need the CMake - build system (http://www.cmake.org/), at least version **2.8.7**. A Subversion client - for Windows, i.e. TortoiseSVN (http://tortoisesvn.tigris.org/), is also required - to download the PCL source code. + build system (http://www.cmake.org/), at least version **2.8.7**. A Git client + for Windows is also required to download the PCL source code. Downloading PCL source code --------------------------- @@ -86,37 +85,9 @@ The invocation to download the source code is thus, using a command line: cd wherever/you/want/to/put/the/repo/ git clone https://github.com/PointCloudLibrary/pcl.git -You could also use Github for Windows( http://windows.github.com/ ), but that is potentially more +You could also use Github for Windows (https://windows.github.com/), but that is potentially more troublesome than setting up git on windows. -Alternatively you could use the old subversion repository: - -For this, -you will need Tortoise SVN to download sources from PCL svn server. - -Subversion is a version control system similar to CVS which allows developers to simultaneously work on PCL. -The download operation of the most recent source from the main development line, known as trunk, is called `checkout`. - -.. note:: - In this tutorial, we will build the svn trunk of PCL. If you want, you can build a PCL branch instead. - You can also build an official release using the source archive from http://pointclouds.org/downloads/. - You can grab PCL branches using Tortoise SVN from : - - - pcl-1.x branch from http://svn.pointclouds.org/pcl/branches/pcl-1.x - - - pcl-1.5.x branch from http://svn.pointclouds.org/pcl/branches/pcl-1.5.x - -First create a folder that will holds PCL source code and binaries. In the remaining of this tutorial we will be using C:\\PCL. -To checkout PCL source code, navigate to the C:\\PCL folder using Windows file manager. Then right click and choose -`SVN Checkout...` from the contextual menu. Set "URL of repository" to http://svn.pointclouds.org/pcl/trunk and -"Checkout directory" to C:\\PCL\\trunk. - -.. image:: images/windows/SVNCheckout_pcl_trunk.png - :alt: SVN Checkout dialog - :align: center - -Click "OK" and the download should start. At the end of this process, you will have PCL source code in C:\\PCL\\trunk. - Configuring PCL --------------- @@ -127,7 +98,7 @@ You can also build static PCL libraries if you want. Run the CMake-gui application and fill in the fields:: - Where is the source code : C:/PCL/trunk + Where is the source code : C:/PCL/pcl Where to build the binaries: C:/PCL Now hit the "Configure" button. You will be asked for a `generator`. A generator is simply a compiler. @@ -352,7 +323,7 @@ Advanced topics Then, you need to enable the `documentation` project in Visual Studio by checking the **BUILD_DOCUMENTATION** checkbox in CMake. You can also build one single CHM file that will gather all the generated html files into one file. You need the `Microsoft - HTML HELP Workshop `_. + HTML HELP Workshop `_. After you install the `Microsoft HTML HELP Workshop`, hit `Configure`. If CMake is not able to find **HTML_HEL_COMPILER**, then fill it manually with the path to `hhc.exe` (e.g. C:/Program Files (x86)/HTML Help Workshop/hhc.exe), then click `Configure` and `Generate`. diff --git a/doc/tutorials/content/correspondence_grouping.rst b/doc/tutorials/content/correspondence_grouping.rst index 272c968a..5331cfe9 100644 --- a/doc/tutorials/content/correspondence_grouping.rst +++ b/doc/tutorials/content/correspondence_grouping.rst @@ -10,8 +10,8 @@ For each cluster, representing a possible model instance in the scene, the Corre The code -------- -Before you begin, you should download the dataset used in this tutorial from `github.com/PointCloudLibrary/data/tree/master/tutorials/correspondence_grouping `_ -and extract the files in a folder of your convenience. +Before you begin, you should download the PCD dataset used in this tutorial from GitHub (`milk.pcd `_ and +`milk_cartoon_all_small_clorox.pcd `_) and put the files in a folder of your convenience. Also, copy and paste the following code into your editor and save it as ``correspondence_grouping.cpp`` (or download the source file :download:`here <./sources/correspondence_grouping/correspondence_grouping.cpp>`). @@ -140,7 +140,7 @@ Alternatively to Hough3DGrouping, and by means of the appropriate command line s :lines: 327-339 .. note:: - The ``recognize`` method returns a vector of ``Eigen::Matrix4f`` representing a transformation (rotation + translation) for each instance of the model found in the scene (obtained via Absolute Orientation) and a **vector** of :pcl:`Correspondences ` (a vector of vectors of :pcl:`Correspondence `) representing the output of the clustering i.e. each element of this vector is in turn a set of correspondences, representing the correspondences associated to a specific model instance in the scene. + The ``recognize`` method returns a vector of ``Eigen::Matrix4f`` representing a transformation (rotation + translation) for each instance of the model found in the scene (obtained via Absolute Orientation) and a **vector** of :pcl:`Correspondences ` (a vector of vectors of :pcl:`Correspondence `) representing the output of the clustering i.e. each element of this vector is in turn a set of correspondences, representing the correspondences associated to a specific model instance in the scene. If you **only** need the clustered correspondences because you are planning to use them in a different way, you can use the ``cluster`` method. @@ -155,7 +155,7 @@ As a first thing we are showing, for each instance of the model found into the s :language: cpp :lines: 344-360 -The program then shows in a :pcl:`PCLVisualizer ` window the scene cloud with a red overlay where an instance of the model has been found. +The program then shows in a :pcl:`PCLVisualizer ` window the scene cloud with a red overlay where an instance of the model has been found. If the command line switches ``-k`` and ``-c`` have been used, the program also shows a "stand-alone" rendering of the model cloud. If keypoint visualization is enabled, keypoints are displayed as blue dots and if correspondence visualization has been enabled they are shown as a green line for each correspondence which *survived* the clustering process. .. literalinclude:: sources/correspondence_grouping/correspondence_grouping.cpp diff --git a/doc/tutorials/content/don_segmentation.rst b/doc/tutorials/content/don_segmentation.rst index 70652f42..4d5b0569 100644 --- a/doc/tutorials/content/don_segmentation.rst +++ b/doc/tutorials/content/don_segmentation.rst @@ -8,7 +8,6 @@ In this tutorial we will learn how to use Difference of Normals features, implem This algorithm performs a scale based segmentation of the given input point cloud, finding points that belong within the scale parameters given. -.. donpipeline:: .. figure:: images/donpipelinesmall.jpg :align: center @@ -28,7 +27,6 @@ Formally the Difference of Normals operator is defined, where :math:`$r_s, r_l \in \mathbb{R}$`, :math:`$r_s`_ +`pcl_features `_ library. The default FPFH implementation uses 11 binning subdivisions (e.g., each of the diff --git a/doc/tutorials/content/generate_local_doc.rst b/doc/tutorials/content/generate_local_doc.rst new file mode 100644 index 00000000..0c71f5e6 --- /dev/null +++ b/doc/tutorials/content/generate_local_doc.rst @@ -0,0 +1,74 @@ +.. _generate_local_doc: + +====================================== +Generate a local documentation for PCL +====================================== + +For practical reasons you might want to have a local documentation which corresponds to your +PCL version. In this tutorial you will learn how to generate it and how to set up Apache so that +the search bar works. + +This tutorial was written for Ubuntu 12.04 and 14.04, feel free to edit it on GitHub to add your platform. + +Dependencies +============ + +You need to install a few dependencies in order to be able to generate the documentation:: + + $ sudo apt-get install doxygen graphviz sphinx3 python-pip + $ sudo pip install sphinxcontrib-doxylink + +Generate the documentation +========================== + +Go into the build folder of PCL where you've configured it (`see tutorial `_) and enter:: + + $ make doc + +Then you can open the documentation with your browser, for example:: + + $ firefox doc/doxygen/html/index.html + +The documentation has been generated in your PCL build directory but it is not installed; if you wish to install it just do:: + + $ sudo make install + +The default PCL ``CMAKE_INSTALL_PREFIX`` is ``/usr/local``, this means the documentation will be located in ``/usr/local/share/doc/pcl-1.7/html/index.html`` + +.. note:: + You will quickly notice that the search bar doesn't work! (searching opens "search.php" instead of searching) + +Installing and configuring Apache +================================= + +Apache (`The Apache HTTP Server `_) is a web server application, in this section you will +learn how to configure Apache in order to be able to use the search feature within your offline documentation. + +First you need to install Apache and php:: + + $ sudo apt-get install apache2 php5 libapache2-mod-php5 + +Then you need to edit the default website location:: + + $ sudo gedit /etc/apache2/sites-available/000-default.conf + +Change ``DocumentRoot`` (default = ``/var/www/html``) to ``/usr/local/share/doc/pcl-1.7/html/`` (or your local PCL doc build path) + +After that change the Apache directory options:: + + $ sudo gedit +153 /etc/apache2/apache2.conf + +Replace the paragraph at line 153 with:: + + + #Options FollowSymLinks + Options Indexes FollowSymLinks Includes ExecCGI + AllowOverride All + Order deny,allow + Allow from all + + +Restart Apache and the search bar will now work if you open ``localhost``:: + + $ sudo /etc/init.d/apache2 restart + $ firefox localhost diff --git a/doc/tutorials/content/images/bspline_bunny.png b/doc/tutorials/content/images/bspline_bunny.png new file mode 100644 index 0000000000000000000000000000000000000000..90fbd1b9cc660d672b2fe22df621f4b8f3915f61 GIT binary patch literal 85570 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